diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index d3962784b..a0da17063 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -418,8 +418,9 @@
-
+
+
@@ -459,12 +460,15 @@
Witcher3View.xaml
-
- LayerEditorView.xaml
-
LayerConditionView.xaml
+
+ LayerDynamicPropertiesView.xaml
+
+
+ LayerEditorView.xaml
+
OverlaysView.xaml
@@ -623,14 +627,18 @@
Designer
MSBuild:Compile
-
- Designer
- MSBuild:Compile
-
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
Designer
MSBuild:Compile
diff --git a/Artemis/Artemis/ItemBehaviours/BindableSelectedItemBehavior.cs b/Artemis/Artemis/ItemBehaviours/BindableSelectedItemBehavior.cs
index a09841ed5..ffb3687ad 100644
--- a/Artemis/Artemis/ItemBehaviours/BindableSelectedItemBehavior.cs
+++ b/Artemis/Artemis/ItemBehaviours/BindableSelectedItemBehavior.cs
@@ -1,4 +1,5 @@
-using System.Windows;
+using System.Collections;
+using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
@@ -44,7 +45,42 @@ namespace Artemis.ItemBehaviours
{
var item = ((BindableSelectedItemBehavior) sender).AssociatedObject
.ItemContainerGenerator.ContainerFromItem(e.NewValue) as TreeViewItem;
- item?.SetValue(TreeViewItem.IsSelectedProperty, true);
+ if (item != null)
+ item.SetValue(TreeViewItem.IsSelectedProperty, true);
+ else
+ ClearTreeViewSelection(((BindableSelectedItemBehavior) sender).AssociatedObject);
+ }
+
+ ///
+ /// Clears a TreeView's selected item recursively
+ /// Tom Wright - http://stackoverflow.com/a/1406116/5015269
+ ///
+ ///
+ public static void ClearTreeViewSelection(TreeView tv)
+ {
+ if (tv != null)
+ ClearTreeViewItemsControlSelection(tv.Items, tv.ItemContainerGenerator);
+ }
+
+ ///
+ /// Clears a TreeView's selected item recursively
+ /// Tom Wright - http://stackoverflow.com/a/1406116/5015269
+ ///
+ ///
+ ///
+ private static void ClearTreeViewItemsControlSelection(ICollection ic, ItemContainerGenerator icg)
+ {
+ if ((ic == null) || (icg == null))
+ return;
+
+ for (var i = 0; i < ic.Count; i++)
+ {
+ var tvi = icg.ContainerFromIndex(i) as TreeViewItem;
+ if (tvi == null)
+ continue;
+ ClearTreeViewItemsControlSelection(tvi.Items, tvi.ItemContainerGenerator);
+ tvi.IsSelected = false;
+ }
}
#endregion
diff --git a/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs
index 04e088568..43af20b1e 100644
--- a/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs
+++ b/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs
@@ -1,68 +1,67 @@
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq.Dynamic;
-using System.Reflection;
+using System.ComponentModel;
using Artemis.Models.Interfaces;
+using Artemis.Utilities;
+using static System.Decimal;
namespace Artemis.Models.Profiles
{
public class LayerDynamicPropertiesModel
{
+ ///
+ /// Property this dynamic property applies on
+ ///
public string LayerProperty { get; set; }
- public string GameProperty { get; set; }
- public string RequiredOperator { get; set; }
- public string RequiredValue { get; set; }
- public LayerPopertyType LayerPopertyType { get; set; }
///
- /// Only used when LayerPropertyType is PercentageOf or PercentageOfProperty
+ /// Property to base the percentage upon
+ ///
+ public string GameProperty { get; set; }
+
+ ///
+ /// Percentage source, the number that defines 100%
///
public string PercentageSource { get; set; }
- internal void ApplyProperty(IGameDataModel dataModel, LayerPropertiesModel userProps,
- LayerPropertiesModel props)
+ ///
+ /// Type of property
+ ///
+ public LayerPropertyType LayerPropertyType { get; set; }
+
+ internal void ApplyProperty(IGameDataModel data, LayerPropertiesModel userProps, LayerPropertiesModel props)
{
- var dataList = new List {(T) dataModel};
-
- // Attempt to set the property
- var layerProp = props.GetType().GetProperty(LayerProperty);
- var layerUserProp = userProps.GetType().GetProperty(LayerProperty);
-
- if (LayerPopertyType == LayerPopertyType.PercentageOf)
- SetPercentageOf(props, userProps, dataModel, int.Parse(PercentageSource));
- if (LayerPopertyType == LayerPopertyType.PercentageOfProperty)
- SetPercentageOfProperty(props, userProps, dataModel);
+ if (LayerPropertyType == LayerPropertyType.PercentageOf)
+ Apply(props, userProps, data, int.Parse(PercentageSource));
+ if (LayerPropertyType == LayerPropertyType.PercentageOfProperty)
+ ApplyProp(props, userProps, data);
}
- private void SetPercentageOf(LayerPropertiesModel props, LayerPropertiesModel userProps,
- IGameDataModel dataModel, int percentageSource)
+ private void Apply(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data,
+ int percentageSource)
{
- // Property that will be set
+ // Property to apply on
var layerProp = props.GetType().GetProperty(LayerProperty);
- // Property to use as a 100%
+ // User's settings
var userProp = userProps.GetType().GetProperty(LayerProperty);
- // Value to use as a source
- var source = dataModel.GetType().GetProperty(GameProperty)?.GetValue(dataModel, null);
- if (layerProp == null || userProp == null || source == null)
+ // Property to base the percentage upon
+ var gameProperty = data.GetPropValue(GameProperty);
+ if (layerProp == null || userProp == null)
return;
- var percentage = double.Parse(source.ToString())/percentageSource;
+ var percentage = ToDouble(gameProperty) / percentageSource;
layerProp.SetValue(props, (int) (percentage*(int) userProp.GetValue(userProps, null)));
}
- private void SetPercentageOfProperty(LayerPropertiesModel props, LayerPropertiesModel userProps,
- IGameDataModel dataModel)
+ private void ApplyProp(LayerPropertiesModel props, LayerPropertiesModel userProps, IGameDataModel data)
{
- var value = dataModel.GetType().GetProperty(PercentageSource)?.GetValue(dataModel, null);
- if (value != null)
- SetPercentageOf(props, userProps, dataModel, (int) value);
+ var value = data.GetPropValue(PercentageSource);
+ Apply(props, userProps, data, value);
}
}
- public enum LayerPopertyType
+ public enum LayerPropertyType
{
- PercentageOf,
- PercentageOfProperty,
- Color
+ [Description("None")] None,
+ [Description("% of")] PercentageOf,
+ [Description("% of property")] PercentageOfProperty
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Models/Profiles/LayerModel.cs b/Artemis/Artemis/Models/Profiles/LayerModel.cs
index fae6b6dc5..23dc597b9 100644
--- a/Artemis/Artemis/Models/Profiles/LayerModel.cs
+++ b/Artemis/Artemis/Models/Profiles/LayerModel.cs
@@ -49,22 +49,6 @@ namespace Artemis.Models.Profiles
[XmlIgnore]
public ProfileModel ParentProfile { get; internal set; }
- #region IChildItem Members
-
- LayerModel IChildItem.Parent
- {
- get { return ParentLayer; }
- set { ParentLayer = value; }
- }
-
- ProfileModel IChildItem.Parent
- {
- get { return ParentProfile; }
- set { ParentProfile = value; }
- }
-
- #endregion
-
public bool ConditionsMet(IGameDataModel dataModel)
{
return Enabled && LayerConditions.All(cm => cm.ConditionMet(dataModel));
@@ -116,7 +100,7 @@ namespace Artemis.Models.Profiles
{
// Fix the sorting just in case
FixOrder();
-
+
int newOrder;
if (moveUp)
newOrder = selectedLayer.Order - 1;
@@ -137,6 +121,22 @@ namespace Artemis.Models.Profiles
for (var i = 0; i < Children.Count; i++)
Children[i].Order = i;
}
+
+ #region IChildItem Members
+
+ LayerModel IChildItem.Parent
+ {
+ get { return ParentLayer; }
+ set { ParentLayer = value; }
+ }
+
+ ProfileModel IChildItem.Parent
+ {
+ get { return ParentProfile; }
+ set { ParentProfile = value; }
+ }
+
+ #endregion
}
public enum LayerType
diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs
index 4a35dcf84..1ec23360d 100644
--- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs
+++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs
@@ -68,6 +68,8 @@ namespace Artemis.Modules.Games.CounterStrike
if (!jsonString.Contains("Counter-Strike: Global Offensive"))
return;
+
+ Debug.WriteLine("Got data");
// Parse the JSON
GameDataModel = JsonConvert.DeserializeObject(jsonString);
}
diff --git a/Artemis/Artemis/Utilities/ExtensionMethods.cs b/Artemis/Artemis/Utilities/ExtensionMethods.cs
index afa91d147..16d37edd9 100644
--- a/Artemis/Artemis/Utilities/ExtensionMethods.cs
+++ b/Artemis/Artemis/Utilities/ExtensionMethods.cs
@@ -24,5 +24,51 @@ namespace Artemis.Utilities
// TODO: Convert ColorHelpers to ExtensionMethods
#endregion
+
+ #region Reflection
+
+ ///
+ /// Gets a value by path
+ /// jheddings - http://stackoverflow.com/a/1954663/5015269
+ ///
+ ///
+ /// Path, such as "TimeOfDay.Minutes"
+ ///
+ public static object GetPropValue(this object obj, string name)
+ {
+ foreach (var part in name.Split('.'))
+ {
+ if (obj == null)
+ return null;
+
+ var type = obj.GetType();
+ var info = type.GetProperty(part);
+ if (info == null)
+ return null;
+
+ obj = info.GetValue(obj, null);
+ }
+ return obj;
+ }
+
+ ///
+ /// Gets a value by path
+ /// jheddings - http://stackoverflow.com/a/1954663/5015269
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static T GetPropValue(this object obj, string name)
+ {
+ var retVal = GetPropValue(obj, name);
+ if (retVal == null)
+ return default(T);
+
+ // throws InvalidCastException if types are incompatible
+ return (T) retVal;
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/GameState/GameStateWebServer.cs b/Artemis/Artemis/Utilities/GameState/GameStateWebServer.cs
index dc1d062f3..44a39c4c4 100644
--- a/Artemis/Artemis/Utilities/GameState/GameStateWebServer.cs
+++ b/Artemis/Artemis/Utilities/GameState/GameStateWebServer.cs
@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Net;
-using System.Text;
using System.Threading;
using System.Windows.Forms;
using Artemis.Settings;
@@ -9,12 +8,18 @@ using Newtonsoft.Json;
namespace Artemis.Utilities.GameState
{
+ ///
+ /// Listens for JSON calls, parses them and raises an event.
+ /// Includes some code from https://github.com/rakijah/CSGSI
+ ///
public class GameStateWebServer
{
public delegate void GameDataReceivedEventHandler(
object sender, GameDataReceivedEventArgs gameDataReceivedEventArgs);
- private readonly HttpListener _listener = new HttpListener();
+ private readonly AutoResetEvent _waitForConnection = new AutoResetEvent(false);
+
+ private HttpListener _listener;
public GameStateWebServer()
{
@@ -31,64 +36,69 @@ namespace Artemis.Utilities.GameState
if (Running)
return;
+ Port = General.Default.GamestatePort;
+
+ _listener = new HttpListener();
+ _listener.Prefixes.Add($"http://localhost:{Port}/");
+ var listenerThread = new Thread(ListenerRun);
try
{
- _listener.Prefixes.Clear();
- Port = General.Default.GamestatePort;
- _listener.Prefixes.Add($"http://localhost:{Port}/");
-
_listener.Start();
}
- catch (Exception)
+ catch (HttpListenerException)
{
- MessageBox.Show("Couldn't start the webserver. CS:GO/Dota2 effects won't work :c \n\nTry changing the port in Settings and restart Artemis.");
+ MessageBox.Show(
+ "Couldn't start the webserver. CS:GO/Dota2 effects won't work :c \n\nTry changing the port in Settings and restart Artemis.");
}
- ThreadPool.QueueUserWorkItem(o =>
- {
- try
- {
- while (_listener.IsListening)
- {
- ThreadPool.QueueUserWorkItem(c =>
- {
- var ctx = c as HttpListenerContext;
- if (ctx == null)
- return;
- try
- {
- HandleRequest(ctx.Request);
- var buf = Encoding.UTF8.GetBytes("ok");
- ctx.Response.ContentLength64 = buf.Length;
- ctx.Response.OutputStream.Write(buf, 0, buf.Length);
- }
- catch
- {
- // ignored
- }
- finally
- {
- // always close the stream
- ctx.Response.OutputStream.Close();
- }
- }, _listener.GetContext());
- }
- }
- catch
- {
- // ignored
- }
- });
-
Running = true;
+ listenerThread.Start();
+ }
+
+ private void ListenerRun()
+ {
+ while (Running)
+ {
+ _listener.BeginGetContext(HandleRequest, _listener);
+ _waitForConnection.WaitOne();
+ _waitForConnection.Reset();
+ }
+ }
+
+ private void HandleRequest(IAsyncResult ar)
+ {
+ HttpListenerContext context = null;
+ try
+ {
+ context = _listener.EndGetContext(ar);
+ }
+ catch (ObjectDisposedException)
+ {
+ // Listener was Closed due to call of Stop();
+ }
+ catch (HttpListenerException)
+ {
+ // Listener was Closed due to call of Stop();
+ }
+ finally
+ {
+ _waitForConnection.Set();
+ }
+
+ if (context != null)
+ {
+ HandleRequest(context.Request);
+ context.Response.OutputStream.Close();
+ }
}
public void Stop()
{
- _listener.Stop();
+ _listener.Close();
+ Running = false;
}
- private string HandleRequest(HttpListenerRequest request)
+ private void HandleRequest(HttpListenerRequest request)
{
object json;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
@@ -99,7 +109,6 @@ namespace Artemis.Utilities.GameState
if (json != null)
OnGameDataReceived(new GameDataReceivedEventArgs(json));
- return JsonConvert.SerializeObject(json);
}
protected virtual void OnGameDataReceived(GameDataReceivedEventArgs e)
diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs
index d426f7732..c1c6f9395 100644
--- a/Artemis/Artemis/Utilities/GeneralHelpers.cs
+++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs
@@ -2,12 +2,9 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
-using System.Linq;
using System.Reflection;
using System.Security.Principal;
using System.Windows;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using static System.String;
namespace Artemis.Utilities
@@ -62,10 +59,7 @@ namespace Artemis.Utilities
if (propertyNames.Length == 1 || value == null)
return value;
- else
- {
- return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
- }
+ return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
public static List GenerateTypeMap(object o) => GenerateTypeMap(o.GetType().GetProperties());
@@ -102,7 +96,9 @@ namespace Artemis.Utilities
if (friendlyName != Empty)
list.Add(parent);
- list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(), path + $"{propertyInfo.Name}."));
+ if (propertyInfo.PropertyType.Name != "String")
+ list.AddRange(GenerateTypeMap(propertyInfo.PropertyType.GetProperties(),
+ path + $"{propertyInfo.Name}."));
}
return list;
}
diff --git a/Artemis/Artemis/Utilities/LayerDrawer.cs b/Artemis/Artemis/Utilities/LayerDrawer.cs
index b0a4e00f1..f14079de8 100644
--- a/Artemis/Artemis/Utilities/LayerDrawer.cs
+++ b/Artemis/Artemis/Utilities/LayerDrawer.cs
@@ -1,7 +1,6 @@
using System;
using System.Windows;
using System.Windows.Media;
-using System.Windows.Media.Imaging;
using Artemis.Models.Profiles;
namespace Artemis.Utilities
@@ -112,46 +111,18 @@ namespace Artemis.Utilities
}
}
- public BitmapImage GetThumbnail()
+ public DrawingImage GetThumbnail()
{
if (_layerModel.UserProps.Brush == null)
return null;
- _rectangle = new Rect(0, 0, 18, 18);
+ var visual = new DrawingVisual();
+ using (var c = visual.RenderOpen())
+ c.DrawRectangle(_layerModel.UserProps.Brush, new Pen(new SolidColorBrush(Colors.White), 1),
+ new Rect(0, 0, 18, 18));
- //var bitmap = new Bitmap(18, 18);
-
- //using (var g = Graphics.FromImage(bitmap))
- //{
- // g.SmoothingMode = SmoothingMode.AntiAlias;
- // if (_layerModel.LayerType == LayerType.KeyboardEllipse)
- // {
- // g.FillEllipse(_layerModel.LayerUserProperties.Brush, _rectangle);
- // g.DrawEllipse(new Pen(Color.Black, 1), 0, 0, 17, 17);
- // }
- // else if (_layerModel.LayerType == LayerType.KeyboardRectangle)
- // {
- // g.FillRectangle(_layerModel.LayerUserProperties.Brush, _rectangle);
- // g.DrawRectangle(new Pen(Color.Black, 1), 0, 0, 17, 17);
- // }
- // else
- // bitmap = Resources.folder;
- //}
-
- //using (var memory = new MemoryStream())
- //{
- // bitmap.Save(memory, ImageFormat.Png);
- // memory.Position = 0;
-
- // var bitmapImage = new BitmapImage();
- // bitmapImage.BeginInit();
- // bitmapImage.StreamSource = memory;
- // bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
- // bitmapImage.EndInit();
-
- // return bitmapImage;
- //}
- return null;
+ var image = new DrawingImage(visual.Drawing);
+ return image;
}
public void DrawRectangle(DrawingContext c)
diff --git a/Artemis/Artemis/ViewModels/LayerEditor/LayerDynamicPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/LayerEditor/LayerDynamicPropertiesViewModel.cs
new file mode 100644
index 000000000..af66f2da7
--- /dev/null
+++ b/Artemis/Artemis/ViewModels/LayerEditor/LayerDynamicPropertiesViewModel.cs
@@ -0,0 +1,103 @@
+using System.ComponentModel;
+using System.Linq;
+using Artemis.Models.Profiles;
+using Artemis.Utilities;
+using Caliburn.Micro;
+
+namespace Artemis.ViewModels.LayerEditor
+{
+ public class LayerDynamicPropertiesViewModel : Screen
+ {
+ private LayerDynamicPropertiesModel _layerDynamicPropertiesModel;
+ private string _name;
+ private GeneralHelpers.PropertyCollection _selectedSource;
+ private GeneralHelpers.PropertyCollection _selectedTarget;
+
+ public LayerDynamicPropertiesViewModel(string property,
+ BindableCollection dataModelProps, LayerModel layer)
+ {
+ // Look for the existing property model
+ LayerDynamicPropertiesModel = layer.LayerProperties.FirstOrDefault(lp => lp.LayerProperty == property);
+ if (LayerDynamicPropertiesModel == null)
+ {
+ // If it doesn't exist, create a new one
+ LayerDynamicPropertiesModel = new LayerDynamicPropertiesModel
+ {
+ LayerProperty = property,
+ LayerPropertyType = LayerPropertyType.None
+ };
+ // Add it to the layer
+ layer.LayerProperties.Add(LayerDynamicPropertiesModel);
+ }
+
+ Name = property + ":";
+ Targets = new BindableCollection();
+ Targets.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
+ Sources = new BindableCollection();
+ Sources.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
+
+ PropertyChanged += OnPropertyChanged;
+ }
+
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ if (value == _name) return;
+ _name = value;
+ NotifyOfPropertyChange(() => Name);
+ }
+ }
+
+ public LayerDynamicPropertiesModel LayerDynamicPropertiesModel
+ {
+ get { return _layerDynamicPropertiesModel; }
+ set
+ {
+ if (Equals(value, _layerDynamicPropertiesModel)) return;
+ _layerDynamicPropertiesModel = value;
+ NotifyOfPropertyChange(() => LayerDynamicPropertiesModel);
+ }
+ }
+
+ public BindableCollection Targets { get; set; }
+
+ public GeneralHelpers.PropertyCollection SelectedTarget
+ {
+ get { return _selectedTarget; }
+ set
+ {
+ if (value.Equals(_selectedTarget)) return;
+ _selectedTarget = value;
+ NotifyOfPropertyChange(() => SelectedTarget);
+ }
+ }
+
+ public BindableCollection Sources { get; set; }
+
+ public GeneralHelpers.PropertyCollection SelectedSource
+ {
+ get { return _selectedSource; }
+ set
+ {
+ if (value.Equals(_selectedSource)) return;
+ _selectedSource = value;
+ NotifyOfPropertyChange(() => SelectedSource);
+ }
+ }
+
+ ///
+ /// Updates the underlying model
+ ///
+ ///
+ ///
+ private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "SelectedTarget")
+ LayerDynamicPropertiesModel.GameProperty = SelectedTarget.Path;
+ if (e.PropertyName == "SelectedSource")
+ LayerDynamicPropertiesModel.PercentageSource = SelectedSource.Path;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/LayerEditorViewModel.cs b/Artemis/Artemis/ViewModels/LayerEditor/LayerEditorViewModel.cs
similarity index 85%
rename from Artemis/Artemis/ViewModels/LayerEditorViewModel.cs
rename to Artemis/Artemis/ViewModels/LayerEditor/LayerEditorViewModel.cs
index 2a6ccd1b0..c4026d2d9 100644
--- a/Artemis/Artemis/ViewModels/LayerEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/LayerEditor/LayerEditorViewModel.cs
@@ -1,149 +1,150 @@
-using System;
-using System.ComponentModel;
-using System.Linq;
-using System.Threading;
-using System.Windows.Media;
-using Artemis.DAL;
-using Artemis.KeyboardProviders;
-using Artemis.Models.Profiles;
-using Artemis.Utilities;
-using Artemis.ViewModels.LayerEditor;
-using Caliburn.Micro;
-
-namespace Artemis.ViewModels
-{
- public class LayerEditorViewModel : Screen
- {
- private readonly KeyboardProvider _activeKeyboard;
- private readonly BackgroundWorker _previewWorker;
- private readonly ProfileModel _profile;
- private readonly bool _wasEnabled;
- private LayerModel _layer;
- private LayerPropertiesModel _proposedProperties;
-
- public LayerEditorViewModel(KeyboardProvider activeKeyboard, ProfileModel profile, LayerModel layer)
- {
- _activeKeyboard = activeKeyboard;
- _profile = profile;
- _wasEnabled = layer.Enabled;
- Layer = layer;
-
- Layer.Enabled = false;
-
- DataModelProps = new BindableCollection();
- ProposedProperties = new LayerPropertiesModel();
- DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap());
-
- LayerConditionVms =
- new BindableCollection>(
- layer.LayerConditions.Select(c => new LayerConditionViewModel(this, c, DataModelProps)));
-
- _previewWorker = new BackgroundWorker {WorkerSupportsCancellation = true};
- _previewWorker.DoWork += PreviewWorkerOnDoWork;
- _previewWorker.RunWorkerAsync();
-
- PropertyChanged += AnimationUiHandler;
- PreSelect();
- }
-
- public BindableCollection DataModelProps { get; set; }
-
- public BindableCollection LayerTypes => new BindableCollection();
-
- public BindableCollection> LayerConditionVms { get; set; }
-
- public LayerModel Layer
- {
- get { return _layer; }
- set
- {
- if (Equals(value, _layer)) return;
- _layer = value;
- NotifyOfPropertyChange(() => Layer);
- }
- }
-
- public LayerPropertiesModel ProposedProperties
- {
- get { return _proposedProperties; }
- set
- {
- if (Equals(value, _proposedProperties)) return;
- _proposedProperties = value;
- NotifyOfPropertyChange(() => ProposedProperties);
- }
- }
-
- public ImageSource LayerImage
- {
- get
- {
- var keyboardRect = _activeKeyboard.KeyboardRectangle(4);
-
- var visual = new DrawingVisual();
- using (var drawingContext = visual.RenderOpen())
- {
- // Setup the DrawingVisual's size
- drawingContext.PushClip(new RectangleGeometry(keyboardRect));
- drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
-
- // Draw the layer
- _layer.DrawPreview(drawingContext);
-
- // Remove the clip
- drawingContext.Pop();
- }
- var image = new DrawingImage(visual.Drawing);
-
- return image;
- }
- }
-
- private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
- {
- while (!_previewWorker.CancellationPending)
- {
- NotifyOfPropertyChange(() => LayerImage);
- Thread.Sleep(1000/25);
- }
- }
-
- public void PreSelect()
- {
- GeneralHelpers.CopyProperties(ProposedProperties, Layer.UserProps);
- }
-
- private void AnimationUiHandler(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName != "_proposedProperties")
- return;
- }
-
- public void AddCondition()
- {
- var condition = new LayerConditionModel();
- Layer.LayerConditions.Add(condition);
- LayerConditionVms.Add(new LayerConditionViewModel(this, condition, DataModelProps));
- }
-
- public void Apply()
- {
- GeneralHelpers.CopyProperties(Layer.UserProps, ProposedProperties);
- ProfileProvider.AddOrUpdate(_profile);
- }
-
- public void DeleteCondition(LayerConditionViewModel layerConditionViewModel,
- LayerConditionModel layerConditionModel)
- {
- LayerConditionVms.Remove(layerConditionViewModel);
- Layer.LayerConditions.Remove(layerConditionModel);
- }
-
- public override void CanClose(Action callback)
- {
- _previewWorker.CancelAsync();
- _layer.Enabled = _wasEnabled;
- base.CanClose(callback);
- }
- }
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading;
+using System.Windows.Media;
+using Artemis.KeyboardProviders;
+using Artemis.Models.Profiles;
+using Artemis.Utilities;
+using Caliburn.Micro;
+
+namespace Artemis.ViewModels.LayerEditor
+{
+ public class LayerEditorViewModel : Screen
+ {
+ private readonly KeyboardProvider _activeKeyboard;
+ private readonly BackgroundWorker _previewWorker;
+ private readonly bool _wasEnabled;
+ private LayerModel _layer;
+ private LayerPropertiesModel _proposedProperties;
+
+ public LayerEditorViewModel(KeyboardProvider activeKeyboard, LayerModel layer)
+ {
+ _activeKeyboard = activeKeyboard;
+ _wasEnabled = layer.Enabled;
+
+ Layer = layer;
+ Layer.Enabled = false;
+ DataModelProps = new BindableCollection();
+ ProposedProperties = new LayerPropertiesModel();
+ DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap());
+ LayerConditionVms = new BindableCollection>(
+ layer.LayerConditions.Select(c => new LayerConditionViewModel(this, c, DataModelProps)));
+ HeightProperties = new LayerDynamicPropertiesViewModel("Height", DataModelProps, layer);
+ WidthProperties = new LayerDynamicPropertiesViewModel("Width", DataModelProps, layer);
+ OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", DataModelProps, layer);
+
+ _previewWorker = new BackgroundWorker {WorkerSupportsCancellation = true};
+ _previewWorker.DoWork += PreviewWorkerOnDoWork;
+ _previewWorker.RunWorkerAsync();
+
+ PropertyChanged += AnimationUiHandler;
+ PreSelect();
+ }
+
+ public LayerDynamicPropertiesViewModel OpacityProperties { get; set; }
+
+ public LayerDynamicPropertiesViewModel WidthProperties { get; set; }
+
+ public LayerDynamicPropertiesViewModel HeightProperties { get; set; }
+
+ public BindableCollection DataModelProps { get; set; }
+
+ public BindableCollection LayerTypes => new BindableCollection();
+
+ public BindableCollection> LayerConditionVms { get; set; }
+
+ public LayerModel Layer
+ {
+ get { return _layer; }
+ set
+ {
+ if (Equals(value, _layer)) return;
+ _layer = value;
+ NotifyOfPropertyChange(() => Layer);
+ }
+ }
+
+ public LayerPropertiesModel ProposedProperties
+ {
+ get { return _proposedProperties; }
+ set
+ {
+ if (Equals(value, _proposedProperties)) return;
+ _proposedProperties = value;
+ NotifyOfPropertyChange(() => ProposedProperties);
+ }
+ }
+
+ public ImageSource LayerImage
+ {
+ get
+ {
+ var keyboardRect = _activeKeyboard.KeyboardRectangle(4);
+
+ var visual = new DrawingVisual();
+ using (var drawingContext = visual.RenderOpen())
+ {
+ // Setup the DrawingVisual's size
+ drawingContext.PushClip(new RectangleGeometry(keyboardRect));
+ drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
+
+ // Draw the layer
+ _layer.DrawPreview(drawingContext);
+
+ // Remove the clip
+ drawingContext.Pop();
+ }
+ var image = new DrawingImage(visual.Drawing);
+
+ return image;
+ }
+ }
+
+ private void PreviewWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
+ {
+ while (!_previewWorker.CancellationPending)
+ {
+ NotifyOfPropertyChange(() => LayerImage);
+ Thread.Sleep(1000/25);
+ }
+ }
+
+ public void PreSelect()
+ {
+ GeneralHelpers.CopyProperties(ProposedProperties, Layer.UserProps);
+ }
+
+ private void AnimationUiHandler(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName != "_proposedProperties")
+ return;
+ }
+
+ public void AddCondition()
+ {
+ var condition = new LayerConditionModel();
+ Layer.LayerConditions.Add(condition);
+ LayerConditionVms.Add(new LayerConditionViewModel(this, condition, DataModelProps));
+ }
+
+ public void Apply()
+ {
+ GeneralHelpers.CopyProperties(Layer.UserProps, ProposedProperties);
+ }
+
+ public void DeleteCondition(LayerConditionViewModel layerConditionViewModel,
+ LayerConditionModel layerConditionModel)
+ {
+ LayerConditionVms.Remove(layerConditionViewModel);
+ Layer.LayerConditions.Remove(layerConditionModel);
+ }
+
+ public override void CanClose(Action callback)
+ {
+ _previewWorker.CancelAsync();
+ _layer.Enabled = _wasEnabled;
+ base.CanClose(callback);
+ }
+ }
}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
index 38f3dc6a6..25a33eb3a 100644
--- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
@@ -15,6 +15,7 @@ using Artemis.KeyboardProviders;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Profiles;
+using Artemis.ViewModels.LayerEditor;
using Caliburn.Micro;
using MahApps.Metro;
@@ -78,6 +79,7 @@ namespace Artemis.ViewModels
if (Equals(value, _selectedLayer)) return;
_selectedLayer = value;
NotifyOfPropertyChange(() => SelectedLayer);
+ NotifyOfPropertyChange(() => CanRemoveLayer);
}
}
@@ -105,6 +107,7 @@ namespace Artemis.ViewModels
NotifyOfPropertyChange(() => SelectedProfile);
NotifyOfPropertyChange(() => CanAddLayer);
+ NotifyOfPropertyChange(() => CanRemoveLayer);
}
}
@@ -169,6 +172,7 @@ namespace Artemis.ViewModels
{
if (ActiveKeyboard?.PreviewSettings.Image == null)
return null;
+
ActiveKeyboard.PreviewSettings.Image.Save(memory, ImageFormat.Png);
memory.Position = 0;
@@ -186,6 +190,7 @@ namespace Artemis.ViewModels
public PreviewSettings? PreviewSettings => ActiveKeyboard?.PreviewSettings;
public bool CanAddLayer => _selectedProfile != null;
+ public bool CanRemoveLayer => _selectedProfile != null && _selectedLayer != null;
private KeyboardProvider ActiveKeyboard => _mainManager.KeyboardManager.ActiveKeyboard;
@@ -197,8 +202,13 @@ namespace Artemis.ViewModels
private void PropertyChangeHandler(object sender, PropertyChangedEventArgs e)
{
- if (e.PropertyName != "KeyboardPreview")
- NotifyOfPropertyChange(() => KeyboardPreview);
+ if (e.PropertyName == "KeyboardPreview")
+ return;
+
+ NotifyOfPropertyChange(() => KeyboardPreview);
+
+ if (SelectedProfile != null)
+ ProfileProvider.AddOrUpdate(SelectedProfile);
}
private void LoadProfiles()
@@ -247,7 +257,7 @@ namespace Artemis.ViewModels
public void LayerEditor(LayerModel layer)
{
IWindowManager manager = new WindowManager();
- _editorVm = new LayerEditorViewModel(ActiveKeyboard, SelectedProfile, layer);
+ _editorVm = new LayerEditorViewModel(ActiveKeyboard, layer);
dynamic settings = new ExpandoObject();
settings.Title = "Artemis | Edit " + layer.Name;
@@ -272,6 +282,16 @@ namespace Artemis.ViewModels
SelectedProfile.Layers.Remove(_selectedLayer);
Layers.Remove(_selectedLayer);
+
+ SelectedProfile.FixOrder();
+ }
+
+ public void RemoveLayer(LayerModel layer)
+ {
+ SelectedProfile.Layers.Remove(layer);
+ Layers.Remove(layer);
+
+ SelectedProfile.FixOrder();
}
public void LayerUp()
@@ -324,8 +344,7 @@ namespace Artemis.ViewModels
var hoverLayer = SelectedProfile.Layers.OrderBy(l => l.Order).Where(l => l.Enabled)
.FirstOrDefault(l => l.UserProps.GetRect(1).Contains(x, y));
- if (hoverLayer != null)
- SelectedLayer = hoverLayer;
+ SelectedLayer = hoverLayer;
}
public void MouseMoveKeyboardPreview(MouseEventArgs e)
diff --git a/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml b/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml
new file mode 100644
index 000000000..bf4cc9107
--- /dev/null
+++ b/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Views/LayerEditorView.xaml.cs b/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml.cs
similarity index 65%
rename from Artemis/Artemis/Views/LayerEditorView.xaml.cs
rename to Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml.cs
index d34a94ff6..bbb08551e 100644
--- a/Artemis/Artemis/Views/LayerEditorView.xaml.cs
+++ b/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml.cs
@@ -1,29 +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.Shapes;
-using MahApps.Metro.Controls;
-using ColorBox;
-
-namespace Artemis.Views
-{
- ///
- /// Interaction logic for LayerEditorView.xaml
- ///
- public partial class LayerEditorView : MetroWindow
- {
- public LayerEditorView()
- {
- InitializeComponent();
- }
- }
-}
+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.Views.LayerEditor
+{
+ ///
+ /// Interaction logic for LayerDynamicPropertiesView.xaml
+ ///
+ public partial class LayerDynamicPropertiesView : UserControl
+ {
+ public LayerDynamicPropertiesView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Views/LayerEditorView.xaml b/Artemis/Artemis/Views/LayerEditor/LayerEditorView.xaml
similarity index 72%
rename from Artemis/Artemis/Views/LayerEditorView.xaml
rename to Artemis/Artemis/Views/LayerEditor/LayerEditorView.xaml
index 0d81496ca..7676dc8a4 100644
--- a/Artemis/Artemis/Views/LayerEditorView.xaml
+++ b/Artemis/Artemis/Views/LayerEditor/LayerEditorView.xaml
@@ -1,151 +1,141 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Views/LayerEditor/LayerEditorView.xaml.cs b/Artemis/Artemis/Views/LayerEditor/LayerEditorView.xaml.cs
new file mode 100644
index 000000000..7bdd84014
--- /dev/null
+++ b/Artemis/Artemis/Views/LayerEditor/LayerEditorView.xaml.cs
@@ -0,0 +1,15 @@
+using MahApps.Metro.Controls;
+
+namespace Artemis.Views.LayerEditor
+{
+ ///
+ /// Interaction logic for LayerEditorView.xaml
+ ///
+ public partial class LayerEditorView : MetroWindow
+ {
+ public LayerEditorView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Artemis/Artemis/Views/ProfileEditorView.xaml b/Artemis/Artemis/Views/ProfileEditorView.xaml
index 366e14708..976417379 100644
--- a/Artemis/Artemis/Views/ProfileEditorView.xaml
+++ b/Artemis/Artemis/Views/ProfileEditorView.xaml
@@ -78,7 +78,7 @@
-
+