Skip to content

Commit 3e32567

Browse files
authored
Merge pull request #388 from YoRyan/fix-unsafe-settings
Save settings immediately upon changing in RunActivity.exe
2 parents 57b8254 + 9b0e7f9 commit 3e32567

File tree

13 files changed

+105
-37
lines changed

13 files changed

+105
-37
lines changed

Source/ORTS.Common/SettingsBase.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ protected enum Source
4545
/// <summary>Translates name of a setting to its source</summary>
4646
protected readonly Dictionary<string, Source> Sources = new Dictionary<string, Source>();
4747

48+
/// <summary>
49+
/// True when the user settings store is in use and will be read from and written to.
50+
/// </summary>
51+
protected bool AllowUserSettings { get; private set; }
52+
4853
/// <summary>
4954
/// Constructor
5055
/// </summary>
@@ -76,9 +81,8 @@ protected SettingsBase(SettingsStore settings)
7681
/// <summary>
7782
/// Load all settings, possibly partly from the given options
7883
/// </summary>
79-
/// <param name="allowUserSettings">Are user settings allowed?</param>
8084
/// <param name="optionsDictionary">???</param>
81-
protected abstract void Load(bool allowUserSettings, Dictionary<string, string> optionsDictionary);
85+
protected abstract void Load(Dictionary<string, string> optionsDictionary);
8286

8387
/// <summary>
8488
/// Save all settings to the store
@@ -103,7 +107,7 @@ protected SettingsBase(SettingsStore settings)
103107
protected void Load(IEnumerable<string> options)
104108
{
105109
// This special command-line option prevents the registry values from being used.
106-
var allowUserSettings = !options.Contains("skip-user-settings", StringComparer.OrdinalIgnoreCase);
110+
AllowUserSettings = !options.Contains("skip-user-settings", StringComparer.OrdinalIgnoreCase);
107111

108112
// Pull apart the command-line options so we can find them by setting name.
109113
var optionsDictionary = new Dictionary<string, string>();
@@ -114,23 +118,22 @@ protected void Load(IEnumerable<string> options)
114118
optionsDictionary[k] = v;
115119
}
116120

117-
Load(allowUserSettings, optionsDictionary);
121+
Load(optionsDictionary);
118122
}
119123

120124
/// <summary>
121125
/// Load a single value from the store, once type of the setting is known
122126
/// </summary>
123-
/// <param name="allowUserSettings">Are user settings allowed for this setting?</param>
124127
/// <param name="optionsDictionary">???</param>
125128
/// <param name="name">name of the setting</param>
126129
/// <param name="type">type of the setting</param>
127-
protected void Load(bool allowUserSettings, Dictionary<string, string> optionsDictionary, string name, Type type)
130+
protected void Load(Dictionary<string, string> optionsDictionary, string name, Type type)
128131
{
129132
// Get the default value.
130133
var defValue = GetDefaultValue(name);
131134

132135
// Read in the user setting, if it exists.
133-
var userValue = allowUserSettings ? SettingStore.GetUserValue(name, type) : null;
136+
var userValue = AllowUserSettings ? SettingStore.GetUserValue(name, type) : null;
134137

135138
// Read in the command-line option, if it exists into optValue.
136139
var propertyNameLower = name.ToLowerInvariant();

Source/ORTS.Settings/FolderSettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ protected override void SetValue(string name, object value)
5353
Folders.Remove(name);
5454
}
5555

56-
protected override void Load(bool allowUserSettings, Dictionary<string, string> optionsDictionary)
56+
protected override void Load(Dictionary<string, string> optionsDictionary)
5757
{
5858
foreach (var name in SettingStore.GetUserNames())
59-
Load(allowUserSettings, optionsDictionary, name, typeof(string));
59+
Load(optionsDictionary, name, typeof(string));
6060
}
6161

6262
public override void Save()

Source/ORTS.Settings/InputSettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ protected override void SetValue(string name, object value)
110110
Commands[(int)GetCommand(name)].PersistentDescriptor = (string)value;
111111
}
112112

113-
protected override void Load(bool allowUserSettings, Dictionary<string, string> optionsDictionary)
113+
protected override void Load(Dictionary<string, string> optionsDictionary)
114114
{
115115
foreach (var command in GetCommands())
116-
Load(allowUserSettings, optionsDictionary, command.ToString(), typeof(string));
116+
Load(optionsDictionary, command.ToString(), typeof(string));
117117
}
118118

119119
public override void Save()

Source/ORTS.Settings/UpdateSettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ protected override void SetValue(string name, object value)
9797
GetProperty(name).SetValue(this, value, null);
9898
}
9999

100-
protected override void Load(bool allowUserSettings, Dictionary<string, string> optionsDictionary)
100+
protected override void Load(Dictionary<string, string> optionsDictionary)
101101
{
102102
foreach (var property in GetProperties())
103-
Load(allowUserSettings, optionsDictionary, property.Name, property.PropertyType);
103+
Load(optionsDictionary, property.Name, property.PropertyType);
104104
}
105105

106106
public override void Save()

Source/ORTS.Settings/UpdateState.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ protected override void SetValue(string name, object value)
7676
GetProperty(name).SetValue(this, value, null);
7777
}
7878

79-
protected override void Load(bool allowUserSettings, Dictionary<string, string> optionsDictionary)
79+
protected override void Load(Dictionary<string, string> optionsDictionary)
8080
{
8181
foreach (var property in GetProperties())
82-
Load(allowUserSettings, optionsDictionary, property.Name, property.PropertyType);
82+
Load(optionsDictionary, property.Name, property.PropertyType);
8383
}
8484

8585
public override void Save()

Source/ORTS.Settings/UserSettings.cs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,18 @@ public UserSettings(IEnumerable<string> options)
461461
Input = new InputSettings(options);
462462
}
463463

464+
/// <summary>
465+
/// Get a saving property from this instance by name.
466+
/// </summary>
467+
public SavingProperty<T> GetSavingProperty<T>(string name)
468+
{
469+
var property = GetProperty(name);
470+
if (property == null)
471+
return null;
472+
else
473+
return new SavingProperty<T>(this, property, AllowUserSettings);
474+
}
475+
464476
public override object GetDefaultValue(string name)
465477
{
466478
var property = GetType().GetProperty(name);
@@ -494,10 +506,10 @@ protected override void SetValue(string name, object value)
494506
GetProperty(name).SetValue(this, value, null);
495507
}
496508

497-
protected override void Load(bool allowUserSettings, Dictionary<string, string> optionsDictionary)
509+
protected override void Load(Dictionary<string, string> optionsDictionary)
498510
{
499511
foreach (var property in GetProperties())
500-
Load(allowUserSettings, optionsDictionary, property.Name, property.PropertyType);
512+
Load(optionsDictionary, property.Name, property.PropertyType);
501513
}
502514

503515
public override void Save()
@@ -541,4 +553,50 @@ public void Log()
541553
}
542554
}
543555
}
556+
557+
/// <summary>
558+
/// A wrapper for a UserSettings property that saves any new values immediately.
559+
/// </summary>
560+
/// <typeparam name="T">Cast values to this type.</typeparam>
561+
public class SavingProperty<T>
562+
{
563+
private readonly UserSettings Settings;
564+
private readonly PropertyInfo Property;
565+
private readonly bool DoSave;
566+
567+
internal SavingProperty(UserSettings settings, PropertyInfo property, bool allowSave = true)
568+
{
569+
Settings = settings;
570+
Property = property;
571+
DoSave = allowSave;
572+
}
573+
574+
/// <summary>
575+
/// Get or set the current value of this property.
576+
/// </summary>
577+
public T Value
578+
{
579+
get => GetValue();
580+
set => SetValue(value);
581+
}
582+
583+
/// <summary>
584+
/// Get the current value of this property.
585+
/// </summary>
586+
public T GetValue()
587+
=> Property.GetValue(Settings) is T cast ? cast : default;
588+
589+
/// <summary>
590+
/// Set the current value of this property.
591+
/// </summary>
592+
public void SetValue(T value)
593+
{
594+
if (!GetValue().Equals(value))
595+
{
596+
Property.SetValue(Settings, value);
597+
if (DoSave)
598+
Settings.Save(Property.Name);
599+
}
600+
}
601+
}
544602
}

Source/RunActivity/Program.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ static void Main(string[] args)
6464
var game = new Game(settings);
6565
game.PushState(new GameStateRunActivity(args));
6666
game.Run();
67-
68-
settings.Save();
6967
}
7068
}
7169
}

Source/RunActivity/Viewer3D/Cameras.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
using Orts.Simulation.Signalling;
3232
using ORTS.Common;
3333
using ORTS.Common.Input;
34+
using ORTS.Settings;
3435

3536
namespace Orts.Viewer3D
3637
{
@@ -1973,6 +1974,7 @@ public void ChangeCab(TrainCar newCar)
19731974

19741975
public class CabCamera : NonTrackingCamera
19751976
{
1977+
private readonly SavingProperty<bool> LetterboxProperty;
19761978
protected int sideLocation;
19771979
public int SideLocation { get { return sideLocation; } }
19781980

@@ -2001,6 +2003,7 @@ public override bool IsUnderground
20012003
public CabCamera(Viewer viewer)
20022004
: base(viewer)
20032005
{
2006+
LetterboxProperty = viewer.Settings.GetSavingProperty<bool>("Letterbox2DCab");
20042007
}
20052008

20062009
protected internal override void Save(BinaryWriter outf)
@@ -2212,7 +2215,7 @@ public override void HandleUserInput(ElapsedTime elapsedTime)
22122215
ScrollRight(false, speed);
22132216
if (UserInput.IsPressed(UserCommand.CameraToggleLetterboxCab))
22142217
{
2215-
Viewer.Settings.Letterbox2DCab = !Viewer.Settings.Letterbox2DCab;
2218+
LetterboxProperty.Value = !LetterboxProperty.Value;
22162219
Viewer.AdjustCabHeight(Viewer.DisplaySize.X, Viewer.DisplaySize.Y);
22172220
if (attachedCar != null)
22182221
Initialize();

Source/RunActivity/Viewer3D/Popups/OSDCars.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using Microsoft.Xna.Framework.Graphics;
2222
using Orts.Simulation.RollingStocks;
2323
using ORTS.Common;
24+
using ORTS.Settings;
2425
using System.Collections.Generic;
2526

2627
namespace Orts.Viewer3D.Popups
@@ -37,12 +38,13 @@ public enum DisplayState
3738
Trains = 0x1,
3839
Cars = 0x2,
3940
}
41+
private readonly SavingProperty<int> StateProperty;
4042
private DisplayState State
4143
{
42-
get => (DisplayState)Owner.Viewer.Settings.OSDCarsState;
44+
get => (DisplayState)StateProperty.Value;
4345
set
4446
{
45-
Owner.Viewer.Settings.OSDCarsState = (int)value;
47+
StateProperty.Value = (int)value;
4648
}
4749
}
4850

@@ -51,6 +53,7 @@ private DisplayState State
5153
public OSDCars(WindowManager owner)
5254
: base(owner, 0, 0, "OSD Cars")
5355
{
56+
StateProperty = owner.Viewer.Settings.GetSavingProperty<int>("OSDCarsState");
5457
}
5558

5659
public override bool Interactive

Source/RunActivity/Viewer3D/Popups/OSDLocations.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using Microsoft.Xna.Framework.Graphics;
2222
using Orts.Simulation;
2323
using ORTS.Common;
24+
using ORTS.Settings;
2425
using System.Collections.Generic;
2526

2627
namespace Orts.Viewer3D.Popups
@@ -40,12 +41,13 @@ public enum DisplayState
4041
All = 0x3,
4142
Auto = 0x7,
4243
}
44+
private readonly SavingProperty<int> StateProperty;
4345
private DisplayState State
4446
{
45-
get => (DisplayState)Owner.Viewer.Settings.OSDLocationsState;
47+
get => (DisplayState)StateProperty.Value;
4648
set
4749
{
48-
Owner.Viewer.Settings.OSDLocationsState = (int)value;
50+
StateProperty.Value = (int)value;
4951
}
5052
}
5153

@@ -61,8 +63,8 @@ private DisplayState State
6163
public OSDLocations(WindowManager owner)
6264
: base(owner, 0, 0, "OSD Locations")
6365
{
66+
StateProperty = owner.Viewer.Settings.GetSavingProperty<int>("OSDLocationsState");
6467
UpdateLabelLists();
65-
if (Platforms.Count + Sidings.Count == 0) State = DisplayState.All;
6668
}
6769

6870
void UpdateLabelLists()

0 commit comments

Comments
 (0)