Skip to content

Commit f89a5c4

Browse files
committed
Merge branch 'master' into CorrectScaling
2 parents ed27f81 + 4dc53b5 commit f89a5c4

File tree

8 files changed

+196
-9
lines changed

8 files changed

+196
-9
lines changed

SimpleStateMachineNodeEditor/App.xaml.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
using System.Reflection;
2-
using System.Windows;
2+
using Microsoft.Extensions.Configuration;
33
using ReactiveUI;
4+
using SimpleStateMachineNodeEditor.Helpers.Configuration;
45
using Splat;
5-
using SimpleStateMachineNodeEditor.Helpers;
66
using SimpleStateMachineNodeEditor.Helpers.Converters;
7+
using Application = System.Windows.Application;
78

89
namespace SimpleStateMachineNodeEditor
910
{
@@ -16,7 +17,18 @@ public App()
1617
{
1718
Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly());
1819
Locator.CurrentMutable.RegisterConstant(new ConverterBoolAndVisibility(), typeof(IBindingTypeConverter));
19-
}
2020

21+
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
22+
IConfigurationRoot configuration = configurationBuilder.Add<WritableJsonConfigurationSource>(s =>
23+
{
24+
s.FileProvider = null;
25+
s.Path = "Settings.json";
26+
s.Optional = true;
27+
s.ReloadOnChange = true;
28+
s.ResolveFileProvider();
29+
}).Build();
30+
31+
Locator.CurrentMutable.RegisterConstant(configuration, typeof(IConfiguration));
32+
}
2133
}
2234
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Converters;
3+
using SimpleStateMachineNodeEditor.Helpers.Enums;
4+
5+
namespace SimpleStateMachineNodeEditor
6+
{
7+
public class AppSettings
8+
{
9+
public class AppearanceSettings
10+
{
11+
[JsonConverter(typeof(StringEnumConverter))]
12+
public Themes Theme { get; set; }
13+
}
14+
15+
public AppearanceSettings Appearance { get; set; }
16+
}
17+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System;
2+
using System.IO;
3+
using Microsoft.Extensions.Configuration.Json;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Linq;
6+
7+
namespace SimpleStateMachineNodeEditor.Helpers.Configuration
8+
{
9+
public class WritableJsonConfigurationProvider : JsonConfigurationProvider
10+
{
11+
public WritableJsonConfigurationProvider(JsonConfigurationSource source) : base(source)
12+
{
13+
}
14+
15+
private void Save(dynamic jsonObj)
16+
{
17+
var fileFullPath = base.Source.FileProvider.GetFileInfo(base.Source.Path).PhysicalPath;
18+
string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented);
19+
File.WriteAllText(fileFullPath, output);
20+
}
21+
22+
private void SetValue(string key, string value, dynamic jsonObj)
23+
{
24+
base.Set(key, value);
25+
var split = key.Split(":");
26+
var context = jsonObj;
27+
for (int i = 0; i < split.Length; i++)
28+
{
29+
var currentKey = split[i];
30+
if (i < split.Length - 1)
31+
{
32+
var child = jsonObj[currentKey];
33+
if (child == null)
34+
{
35+
context[currentKey] = new JObject();
36+
}
37+
context = context[currentKey];
38+
}
39+
else
40+
{
41+
context[currentKey] = value;
42+
}
43+
}
44+
}
45+
46+
private dynamic GetJsonObj()
47+
{
48+
var fileFullPath = base.Source.FileProvider.GetFileInfo(base.Source.Path).PhysicalPath;
49+
var json = File.Exists(fileFullPath) ? File.ReadAllText(fileFullPath) : "{}";
50+
return JsonConvert.DeserializeObject(json);
51+
}
52+
53+
public override void Set(string key, string value)
54+
{
55+
var jsonObj = GetJsonObj();
56+
SetValue(key, value, jsonObj);
57+
Save(jsonObj);
58+
}
59+
60+
public void Set(string key, object value)
61+
{
62+
var jsonObj = GetJsonObj();
63+
var serialized = JsonConvert.SerializeObject(value);
64+
var jToken = JsonConvert.DeserializeObject(serialized) as JToken ?? new JValue(value);
65+
WalkAndSet(key, jToken, jsonObj);
66+
Save(jsonObj);
67+
}
68+
69+
private void WalkAndSet(string key, JToken value, dynamic jsonObj)
70+
{
71+
switch (value)
72+
{
73+
case JArray jArray:
74+
{
75+
//TODO Realize arrays
76+
break;
77+
}
78+
case JObject jObject:
79+
{
80+
foreach (var propertyInfo in jObject.Properties())
81+
{
82+
var propName = propertyInfo.Name;
83+
var currentKey = key == null ? propName : $"{key}:{propName}";
84+
var propValue = propertyInfo.Value;
85+
WalkAndSet(currentKey, propValue, jsonObj);
86+
}
87+
break;
88+
}
89+
case JValue jValue:
90+
{
91+
SetValue(key, jValue.ToString(), jsonObj);
92+
break;
93+
}
94+
default:
95+
throw new ArgumentOutOfRangeException(nameof(value));
96+
}
97+
}
98+
}
99+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Linq;
3+
using System.Reflection;
4+
using Microsoft.Extensions.Configuration;
5+
6+
namespace SimpleStateMachineNodeEditor.Helpers.Configuration
7+
{
8+
public static class WritableJsonConfigurationProviderExtensions
9+
{
10+
public static void Set(this IConfiguration configuration, object value)
11+
{
12+
switch (configuration)
13+
{
14+
case IConfigurationRoot configurationRoot:
15+
{
16+
var provider = configurationRoot.Providers.First(p => p is WritableJsonConfigurationProvider) as WritableJsonConfigurationProvider;
17+
provider.Set(null, value);
18+
break;
19+
}
20+
case ConfigurationSection configurationSection:
21+
{
22+
var rootProp = typeof(ConfigurationSection).GetField("_root", BindingFlags.NonPublic | BindingFlags.Instance); ;
23+
var root = rootProp.GetValue(configurationSection) as IConfigurationRoot;
24+
var provider = root.Providers.First(p => p is WritableJsonConfigurationProvider) as WritableJsonConfigurationProvider;
25+
provider.Set(configurationSection.Path, value);
26+
break;
27+
}
28+
default:
29+
throw new ArgumentOutOfRangeException(nameof(configuration));
30+
}
31+
}
32+
}
33+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Microsoft.Extensions.Configuration;
2+
using Microsoft.Extensions.Configuration.Json;
3+
4+
namespace SimpleStateMachineNodeEditor.Helpers.Configuration
5+
{
6+
public class WritableJsonConfigurationSource : JsonConfigurationSource
7+
{
8+
public override IConfigurationProvider Build(IConfigurationBuilder builder)
9+
{
10+
this.EnsureDefaults(builder);
11+
return (IConfigurationProvider)new WritableJsonConfigurationProvider(this);
12+
}
13+
}
14+
}

SimpleStateMachineNodeEditor/SimpleStateMachineNodeEditor.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ ReactiveUI 11.4.17</PackageReleaseNotes>
6262
</ItemGroup>
6363

6464
<ItemGroup>
65+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.5" />
66+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.5" />
67+
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
6568
<PackageReference Include="ReactiveUI" Version="11.4.17" />
6669
<PackageReference Include="ReactiveUI.Events.WPF" Version="11.4.17" />
6770
<PackageReference Include="ReactiveUI.Fody" Version="11.4.17" />

SimpleStateMachineNodeEditor/ViewModel/NodesCanvas/ViewModelNodesCanvas.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System.Windows.Controls;
1616
using System.Windows.Media;
1717
using DynamicData;
18+
using Microsoft.Extensions.Configuration;
1819

1920
namespace SimpleStateMachineNodeEditor.ViewModel
2021
{
@@ -45,10 +46,10 @@ public partial class ViewModelNodesCanvas : ReactiveObject
4546
/// Flag for close application
4647
/// </summary>
4748
[Reactive] public bool NeedExit { get; set; }
48-
[Reactive] public string ImagePath{ get; set; }
49+
[Reactive] public string ImagePath { get; set; }
4950
[Reactive] public ImageFormats ImageFormat { get; set; }
5051
[Reactive] public bool WithoutMessages { get; set; }
51-
[Reactive] public Themes Theme { get; set; } = Themes.Dark;
52+
[Reactive] public Themes Theme { get; set; }
5253

5354

5455

@@ -63,10 +64,14 @@ public partial class ViewModelNodesCanvas : ReactiveObject
6364
public double ScaleMax = 5;
6465
public double ScaleMin = 0.1;
6566
public double Scales { get; set; } = 0.05;
66-
67+
6768

6869
public ViewModelNodesCanvas()
6970
{
71+
var configuration = Locator.Current.GetService<IConfiguration>();
72+
Theme = configuration.GetSection("Appearance:Theme").Get<Themes>();
73+
if (Theme == Themes.noCorrect) Theme = Themes.Dark;
74+
SetTheme(Theme);
7075
Cutter = new ViewModelCutter(this);
7176
Nodes.Connect().ObserveOnDispatcher().Bind(NodesForView).Subscribe();
7277
SetupCommands();
@@ -107,7 +112,7 @@ private void SetAsStart(ViewModelNode node)
107112

108113
public void LogDebug(string message, params object[] args)
109114
{
110-
if(!WithoutMessages)
115+
if (!WithoutMessages)
111116
Messages.Add(new ViewModelMessage(TypeMessage.Debug, string.Format(message, args)));
112117
}
113118
public void LogError(string message, params object[] args)
@@ -133,7 +138,7 @@ private void UpdateCount(int oldValue, int newValue)
133138
if (newValue > oldValue)
134139
{
135140
NodesCount++;
136-
}
141+
}
137142
}
138143
private string SchemeName()
139144
{

SimpleStateMachineNodeEditor/ViewModel/NodesCanvas/ViewModelNodesCanvasCommands.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
using System.Windows;
1313
using System.Windows.Input;
1414
using System.Xml.Linq;
15+
using Microsoft.Extensions.Configuration;
16+
using SimpleStateMachineNodeEditor.Helpers.Configuration;
17+
using Splat;
1518

1619
namespace SimpleStateMachineNodeEditor.ViewModel
1720
{
@@ -137,7 +140,6 @@ private void SetupCommands()
137140
CommandChangeNodeName = new Command<(ViewModelNode node, string newName), (ViewModelNode node, string oldName)>(ChangeNodeName, UnChangeNodeName);
138141
CommandChangeConnectName = new Command<(ViewModelConnector connector, string newName), (ViewModelConnector connector, string oldName)>(ChangeConnectName, UnChangeConnectName);
139142

140-
141143
NotSavedSubscrube();
142144
}
143145

@@ -189,6 +191,8 @@ private void ChangeTheme()
189191
}
190192
private void SetTheme(Themes theme)
191193
{
194+
var configuration = Locator.Current.GetService<IConfiguration>();
195+
configuration.GetSection("Appearance:Theme").Set(theme);
192196
Application.Current.Resources.Clear();
193197
var uri = new Uri(themesPaths[theme], UriKind.RelativeOrAbsolute);
194198
ResourceDictionary resourceDict = Application.LoadComponent(uri) as ResourceDictionary;

0 commit comments

Comments
 (0)