Skip to content

Commit

Permalink
Fixes #2663 - No more nested classes (#2664)
Browse files Browse the repository at this point in the history
* Move all public nested classes out into own files

* Move more nested classes out

* Tidy up and treat CA1034 as an error.  Fix remaining nested classes.

* Remove partial keyword from ThemeManager as it is no longer needed

* Rename Bar to BarSeriesBar to more clearly indicate it is part of GraphView subsystem

* Fix xmldoc references

* Revert nesting changes to ConsoleDrivers

* Change to file scoped namespaces and revert renames

- LineCanvasCell back to just Cell
- ApplicationRunState back to just RunState

* Switch to file scoped namespaces
  • Loading branch information
tznind authored May 23, 2023
1 parent 24ce908 commit e2feeef
Show file tree
Hide file tree
Showing 66 changed files with 1,859 additions and 1,809 deletions.
75 changes: 0 additions & 75 deletions Terminal.Gui/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,81 +324,6 @@ static void ResetState ()
/// </remarks>
public static event EventHandler<ToplevelEventArgs> NotifyStopRunState;

/// <summary>
/// The execution state for a <see cref="Toplevel"/> view.
/// </summary>
public class RunState : IDisposable {
/// <summary>
/// Initializes a new <see cref="RunState"/> class.
/// </summary>
/// <param name="view"></param>
public RunState (Toplevel view)
{
Toplevel = view;
}
/// <summary>
/// The <see cref="Toplevel"/> belonging to this <see cref="RunState"/>.
/// </summary>
public Toplevel Toplevel { get; internal set; }

#if DEBUG_IDISPOSABLE
/// <summary>
/// For debug (see DEBUG_IDISPOSABLE define) purposes to verify objects are being disposed properly
/// </summary>
public bool WasDisposed = false;

/// <summary>
/// For debug (see DEBUG_IDISPOSABLE define) purposes to verify objects are being disposed properly
/// </summary>
public int DisposedCount = 0;

/// <summary>
/// For debug (see DEBUG_IDISPOSABLE define) purposes; the runstate instances that have been created
/// </summary>
public static List<RunState> Instances = new List<RunState> ();

/// <summary>
/// Creates a new RunState object.
/// </summary>
public RunState ()
{
Instances.Add (this);
}
#endif

/// <summary>
/// Releases all resource used by the <see cref="Application.RunState"/> object.
/// </summary>
/// <remarks>
/// Call <see cref="Dispose()"/> when you are finished using the <see cref="Application.RunState"/>.
/// </remarks>
/// <remarks>
/// <see cref="Dispose()"/> method leaves the <see cref="Application.RunState"/> in an unusable state. After
/// calling <see cref="Dispose()"/>, you must release all references to the
/// <see cref="Application.RunState"/> so the garbage collector can reclaim the memory that the
/// <see cref="Application.RunState"/> was occupying.
/// </remarks>
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
#if DEBUG_IDISPOSABLE
WasDisposed = true;
#endif
}

/// <summary>
/// Releases all resource used by the <see cref="Application.RunState"/> object.
/// </summary>
/// <param name="disposing">If set to <see langword="true"/> we are disposing and should dispose held objects.</param>
protected virtual void Dispose (bool disposing)
{
if (Toplevel != null && disposing) {
throw new InvalidOperationException ("You must clean up (Dispose) the Toplevel before calling Application.RunState.Dispose");
}
}
}

/// <summary>
/// Building block API: Prepares the provided <see cref="Toplevel"/> for execution.
/// </summary>
Expand Down
61 changes: 29 additions & 32 deletions Terminal.Gui/Configuration/AppScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,34 @@

#nullable enable

namespace Terminal.Gui {
namespace Terminal.Gui;

public static partial class ConfigurationManager {
/// <summary>
/// The <see cref="Scope{T}"/> class for application-defined configuration settings.
/// </summary>
/// <remarks>
/// </remarks>
/// <example>
/// <para>
/// Use the <see cref="SerializableConfigurationProperty"/> attribute to mark properties that should be serialized as part
/// of application-defined configuration settings.
/// </para>
/// <code>
/// public class MyAppSettings {
/// [SerializableConfigurationProperty (Scope = typeof (AppScope))]
/// public static bool? MyProperty { get; set; } = true;
/// }
/// </code>
/// <para>
/// THe resultant Json will look like this:
/// </para>
/// <code>
/// "AppSettings": {
/// "MyAppSettings.MyProperty": true,
/// "UICatalog.ShowStatusBar": true
/// },
/// </code>
/// </example>
[JsonConverter (typeof (ScopeJsonConverter<AppScope>))]
public class AppScope : Scope<AppScope> {
}
}
/// <summary>
/// The <see cref="Scope{T}"/> class for application-defined configuration settings.
/// </summary>
/// <remarks>
/// </remarks>
/// <example>
/// <para>
/// Use the <see cref="SerializableConfigurationProperty"/> attribute to mark properties that should be serialized as part
/// of application-defined configuration settings.
/// </para>
/// <code>
/// public class MyAppSettings {
/// [SerializableConfigurationProperty (Scope = typeof (AppScope))]
/// public static bool? MyProperty { get; set; } = true;
/// }
/// </code>
/// <para>
/// THe resultant Json will look like this:
/// </para>
/// <code>
/// "AppSettings": {
/// "MyAppSettings.MyProperty": true,
/// "UICatalog.ShowStatusBar": true
/// },
/// </code>
/// </example>
[JsonConverter (typeof (ScopeJsonConverter<AppScope>))]
public class AppScope : Scope<AppScope> {
}
97 changes: 97 additions & 0 deletions Terminal.Gui/Configuration/ConfigProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System;
using System.Reflection;
using System.Text.Json.Serialization;

#nullable enable

namespace Terminal.Gui;

/// <summary>
/// Holds a property's value and the <see cref="PropertyInfo"/> that allows <see cref="ConfigurationManager"/>
/// to get and set the property's value.
/// </summary>
/// <remarks>
/// Configuration properties must be <see langword="public"/> and <see langword="static"/>
/// and have the <see cref="SerializableConfigurationProperty"/>
/// attribute. If the type of the property requires specialized JSON serialization,
/// a <see cref="JsonConverter"/> must be provided using
/// the <see cref="JsonConverterAttribute"/> attribute.
/// </remarks>
public class ConfigProperty {
private object? propertyValue;

/// <summary>
/// Describes the property.
/// </summary>
public PropertyInfo? PropertyInfo { get; set; }

/// <summary>
/// Helper to get either the Json property named (specified by [JsonPropertyName(name)]
/// or the actual property name.
/// </summary>
/// <param name="pi"></param>
/// <returns></returns>
public static string GetJsonPropertyName (PropertyInfo pi)
{
var jpna = pi.GetCustomAttribute (typeof (JsonPropertyNameAttribute)) as JsonPropertyNameAttribute;
return jpna?.Name ?? pi.Name;
}

/// <summary>
/// Holds the property's value as it was either read from the class's implementation or from a config file.
/// If the property has not been set (e.g. because no configuration file specified a value),
/// this will be <see langword="null"/>.
/// </summary>
/// <remarks>
/// On <see langword="set"/>, performs a sparse-copy of the new value to the existing value (only copies elements of
/// the object that are non-null).
/// </remarks>
public object? PropertyValue {
get => propertyValue;
set {
propertyValue = value;
}
}

internal object? UpdateValueFrom (object source)
{
if (source == null) {
return PropertyValue;
}

var ut = Nullable.GetUnderlyingType (PropertyInfo!.PropertyType);
if (source.GetType () != PropertyInfo!.PropertyType && (ut != null && source.GetType () != ut)) {
throw new ArgumentException ($"The source object ({PropertyInfo!.DeclaringType}.{PropertyInfo!.Name}) is not of type {PropertyInfo!.PropertyType}.");
}
if (PropertyValue != null && source != null) {
PropertyValue = ConfigurationManager.DeepMemberwiseCopy (source, PropertyValue);
} else {
PropertyValue = source;
}

return PropertyValue;
}

/// <summary>
/// Retrieves (using reflection) the value of the static property described in <see cref="PropertyInfo"/>
/// into <see cref="PropertyValue"/>.
/// </summary>
/// <returns></returns>
public object? RetrieveValue ()
{
return PropertyValue = PropertyInfo!.GetValue (null);
}

/// <summary>
/// Applies the <see cref="PropertyValue"/> to the property described by <see cref="PropertyInfo"/>.
/// </summary>
/// <returns></returns>
public bool Apply ()
{
if (PropertyValue != null) {
PropertyInfo?.SetValue (null, ConfigurationManager.DeepMemberwiseCopy (PropertyValue, PropertyInfo?.GetValue (null)));
}
return PropertyValue != null;
}

}
116 changes: 2 additions & 114 deletions Terminal.Gui/Configuration/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,118 +69,6 @@ public static partial class ConfigurationManager {
},
};

/// <summary>
/// An attribute that can be applied to a property to indicate that it should included in the configuration file.
/// </summary>
/// <example>
/// [SerializableConfigurationProperty(Scope = typeof(Configuration.ThemeManager.ThemeScope)), JsonConverter (typeof (JsonStringEnumConverter))]
/// public static LineStyle DefaultBorderStyle {
/// ...
/// </example>
[AttributeUsage (AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class SerializableConfigurationProperty : System.Attribute {
/// <summary>
/// Specifies the scope of the property.
/// </summary>
public Type? Scope { get; set; }

/// <summary>
/// If <see langword="true"/>, the property will be serialized to the configuration file using only the property name
/// as the key. If <see langword="false"/>, the property will be serialized to the configuration file using the
/// property name pre-pended with the classname (e.g. <c>Application.UseSystemConsole</c>).
/// </summary>
public bool OmitClassName { get; set; }
}

/// <summary>
/// Holds a property's value and the <see cref="PropertyInfo"/> that allows <see cref="ConfigurationManager"/>
/// to get and set the property's value.
/// </summary>
/// <remarks>
/// Configuration properties must be <see langword="public"/> and <see langword="static"/>
/// and have the <see cref="SerializableConfigurationProperty"/>
/// attribute. If the type of the property requires specialized JSON serialization,
/// a <see cref="JsonConverter"/> must be provided using
/// the <see cref="JsonConverterAttribute"/> attribute.
/// </remarks>
public class ConfigProperty {
private object? propertyValue;

/// <summary>
/// Describes the property.
/// </summary>
public PropertyInfo? PropertyInfo { get; set; }

/// <summary>
/// Helper to get either the Json property named (specified by [JsonPropertyName(name)]
/// or the actual property name.
/// </summary>
/// <param name="pi"></param>
/// <returns></returns>
public static string GetJsonPropertyName (PropertyInfo pi)
{
var jpna = pi.GetCustomAttribute (typeof (JsonPropertyNameAttribute)) as JsonPropertyNameAttribute;
return jpna?.Name ?? pi.Name;
}

/// <summary>
/// Holds the property's value as it was either read from the class's implementation or from a config file.
/// If the property has not been set (e.g. because no configuration file specified a value),
/// this will be <see langword="null"/>.
/// </summary>
/// <remarks>
/// On <see langword="set"/>, performs a sparse-copy of the new value to the existing value (only copies elements of
/// the object that are non-null).
/// </remarks>
public object? PropertyValue {
get => propertyValue;
set {
propertyValue = value;
}
}

internal object? UpdateValueFrom (object source)
{
if (source == null) {
return PropertyValue;
}

var ut = Nullable.GetUnderlyingType (PropertyInfo!.PropertyType);
if (source.GetType () != PropertyInfo!.PropertyType && (ut != null && source.GetType () != ut)) {
throw new ArgumentException ($"The source object ({PropertyInfo!.DeclaringType}.{PropertyInfo!.Name}) is not of type {PropertyInfo!.PropertyType}.");
}
if (PropertyValue != null && source != null) {
PropertyValue = DeepMemberwiseCopy (source, PropertyValue);
} else {
PropertyValue = source;
}

return PropertyValue;
}

/// <summary>
/// Retrieves (using reflection) the value of the static property described in <see cref="PropertyInfo"/>
/// into <see cref="PropertyValue"/>.
/// </summary>
/// <returns></returns>
public object? RetrieveValue ()
{
return PropertyValue = PropertyInfo!.GetValue (null);
}

/// <summary>
/// Applies the <see cref="PropertyValue"/> to the property described by <see cref="PropertyInfo"/>.
/// </summary>
/// <returns></returns>
public bool Apply ()
{
if (PropertyValue != null) {
PropertyInfo?.SetValue (null, DeepMemberwiseCopy (PropertyValue, PropertyInfo?.GetValue (null)));
}
return PropertyValue != null;
}
}

/// <summary>
/// A dictionary of all properties in the Terminal.Gui project that are decorated with the <see cref="SerializableConfigurationProperty"/> attribute.
/// The keys are the property names pre-pended with the class that implements the property (e.g. <c>Application.UseSystemConsole</c>).
Expand All @@ -190,7 +78,7 @@ public bool Apply ()
/// <remarks>
/// Is <see langword="null"/> until <see cref="Initialize"/> is called.
/// </remarks>
private static Dictionary<string, ConfigProperty>? _allConfigProperties;
internal static Dictionary<string, ConfigProperty>? _allConfigProperties;

/// <summary>
/// The backing property for <see cref="Settings"/>.
Expand Down Expand Up @@ -319,7 +207,7 @@ internal static Stream ToStream ()

internal static StringBuilder jsonErrors = new StringBuilder ();

private static void AddJsonError (string error)
internal static void AddJsonError (string error)
{
Debug.WriteLine ($"ConfigurationManager: {error}");
jsonErrors.AppendLine (error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public ConfigurationManagerEventArgs ()
}

/// <summary>
/// Event arguments for the <see cref="ConfigurationManager.ThemeManager"/> events.
/// Event arguments for the <see cref="ThemeManager"/> events.
/// </summary>
public class ThemeManagerEventArgs : EventArgs {
/// <summary>
Expand Down
Loading

0 comments on commit e2feeef

Please sign in to comment.