Skip to content

Commit

Permalink
Merge pull request gui-cs#3843 from tig/v2_3841-ConfigManager
Browse files Browse the repository at this point in the history
Fixes gui-cs#3841 - `ConfigurationManager` not loading correctly
  • Loading branch information
tig authored Nov 23, 2024
2 parents 661b904 + 61bfe2f commit 2a30e9e
Show file tree
Hide file tree
Showing 35 changed files with 700 additions and 247 deletions.
3 changes: 3 additions & 0 deletions Example/Example.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using System;
using Terminal.Gui;

// Override the default configuraiton for the application to use the Light theme
ConfigurationManager.RuntimeConfig = """{ "Theme": "Light" }""";

Application.Run<ExampleWindow> ().Dispose ();

// Before the application exits, reset Terminal.Gui for clean shutdown
Expand Down
6 changes: 3 additions & 3 deletions Terminal.Gui/Application/Application.Initialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,14 @@ internal static void InternalInit (
// We're running unit tests. Disable loading config files other than default
if (Locations == ConfigLocations.All)
{
Locations = ConfigLocations.DefaultOnly;
Locations = ConfigLocations.Default;
Reset ();
}
}
}

AddApplicationKeyBindings ();

// Start the process of configuration management.
// Note that we end up calling LoadConfigurationFromAllSources
// multiple times. We need to do this because some settings are only
Expand All @@ -106,8 +108,6 @@ internal static void InternalInit (
}
Apply ();

AddApplicationKeyBindings ();

// Ignore Configuration for ForceDriver if driverName is specified
if (!string.IsNullOrEmpty (driverName))
{
Expand Down
10 changes: 9 additions & 1 deletion Terminal.Gui/Application/Application.Keyboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,15 @@ private static void ReplaceKey (Key oldKey, Key newKey)
}
else
{
KeyBindings.ReplaceKey (oldKey, newKey);
if (KeyBindings.TryGet(oldKey, out KeyBinding binding))
{
KeyBindings.Remove (oldKey);
KeyBindings.Add (newKey, binding);
}
else
{
KeyBindings.Add (newKey, binding);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions Terminal.Gui/Application/Application.Run.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#nullable enable
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Terminal.Gui;
Expand Down
57 changes: 57 additions & 0 deletions Terminal.Gui/Configuration/ConfigLocations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#nullable enable
namespace Terminal.Gui;

/// <summary>
/// Describes the location of the configuration files. The constants can be combined (bitwise) to specify multiple
/// locations. The more significant the bit, the higher the priority meaning that the last location will override the
/// earlier ones.
/// </summary>

[Flags]
public enum ConfigLocations
{
/// <summary>No configuration will be loaded.</summary>
/// <remarks>
/// Used for development and testing only. For Terminal,Gui to function properly, at least
/// <see cref="Default"/> should be set.
/// </remarks>
None = 0,

/// <summary>
/// Deafult configuration in <c>Terminal.Gui.dll</c>'s resources (<c>Terminal.Gui.Resources.config.json</c>).
/// </summary>
Default = 0b_0000_0001,

/// <summary>
/// Global settings in the current directory (e.g. <c>./.tui/config.json</c>).
/// </summary>
GlobalCurrent = 0b_0000_0010,

/// <summary>
/// Global settings in the home directory (e.g. <c>~/.tui/config.json</c>).
/// </summary>
GlobalHome = 0b_0000_0100,

/// <summary>
/// App resources (e.g. <c>MyApp.Resources.config.json</c>).
/// </summary>
AppResources = 0b_0000_1000,

/// <summary>
/// App settings in the current directory (e.g. <c>./.tui/MyApp.config.json</c>).
/// </summary>
AppCurrent = 0b_0001_0000,

/// <summary>
/// App settings in the home directory (e.g. <c>~/.tui/MyApp.config.json</c>).
/// </summary>
AppHome = 0b_0010_0000,

/// <summary>
/// Settings in the <see cref="ConfigurationManager.RuntimeConfig"/> static property.
/// </summary>
Runtime = 0b_0100_0000,

/// <summary>This constant is a combination of all locations</summary>
All = 0b_1111_1111
}
58 changes: 31 additions & 27 deletions Terminal.Gui/Configuration/ConfigProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,44 +31,42 @@ public class ConfigProperty
/// </remarks>
public object? PropertyValue { get; set; }

/// <summary>Applies the <see cref="PropertyValue"/> to the property described by <see cref="PropertyInfo"/>.</summary>
/// <summary>Applies the <see cref="PropertyValue"/> to the static property described by <see cref="PropertyInfo"/>.</summary>
/// <returns></returns>
public bool Apply ()
{
if (PropertyValue is { })
try
{
try
if (PropertyInfo?.GetValue (null) is { })
{
if (PropertyInfo?.GetValue (null) is { })
{
PropertyInfo?.SetValue (null, DeepMemberWiseCopy (PropertyValue, PropertyInfo?.GetValue (null)));
}
var val = DeepMemberWiseCopy (PropertyValue, PropertyInfo?.GetValue (null));
PropertyInfo?.SetValue (null, val);
}
catch (TargetInvocationException tie)
}
catch (TargetInvocationException tie)
{
// Check if there is an inner exception
if (tie.InnerException is { })
{
// Check if there is an inner exception
if (tie.InnerException is { })
{
// Handle the inner exception separately without catching the outer exception
Exception? innerException = tie.InnerException;
// Handle the inner exception separately without catching the outer exception
Exception? innerException = tie.InnerException;

// Handle the inner exception here
throw new JsonException (
$"Error Applying Configuration Change: {innerException.Message}",
innerException
);
}

// Handle the outer exception or rethrow it if needed
throw new JsonException ($"Error Applying Configuration Change: {tie.Message}", tie);
}
catch (ArgumentException ae)
{
// Handle the inner exception here
throw new JsonException (
$"Error Applying Configuration Change ({PropertyInfo?.Name}): {ae.Message}",
ae
$"Error Applying Configuration Change: {innerException.Message}",
innerException
);
}

// Handle the outer exception or rethrow it if needed
throw new JsonException ($"Error Applying Configuration Change: {tie.Message}", tie);
}
catch (ArgumentException ae)
{
throw new JsonException (
$"Error Applying Configuration Change ({PropertyInfo?.Name}): {ae.Message}",
ae
);
}

return PropertyValue != null;
Expand All @@ -94,6 +92,12 @@ public static string GetJsonPropertyName (PropertyInfo pi)
/// <returns></returns>
public object? RetrieveValue () { return PropertyValue = PropertyInfo!.GetValue (null); }

/// <summary>
/// Updates (using reflection) <see cref="PropertyValue"/> with the value in <paramref name="source"/> using a deep memberwise copy.
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
internal object? UpdateValueFrom (object source)
{
if (source is null)
Expand Down
Loading

0 comments on commit 2a30e9e

Please sign in to comment.