using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text.Json.Serialization;
using static Terminal.Gui.Configuration.ConfigurationManager;
#nullable enable
namespace Terminal.Gui.Configuration {
public static partial class ConfigurationManager {
///
/// The root object for a Theme. A Theme is a set of settings that are applied to the running
/// as a group.
///
///
///
///
///
///
/// "Default": {
/// "ColorSchemes": [
/// {
/// "TopLevel": {
/// "Normal": {
/// "Foreground": "BrightGreen",
/// "Background": "Black"
/// },
/// "Focus": {
/// "Foreground": "White",
/// "Background": "Cyan"
///
/// },
/// "HotNormal": {
/// "Foreground": "Brown",
/// "Background": "Black"
///
/// },
/// "HotFocus": {
/// "Foreground": "Blue",
/// "Background": "Cyan"
/// },
/// "Disabled": {
/// "Foreground": "DarkGray",
/// "Background": "Black"
///
/// }
/// }
///
[JsonConverter (typeof (ScopeJsonConverter))]
public class ThemeScope : Scope {
///
internal override bool Apply ()
{
var ret = base.Apply ();
Application.Driver?.InitalizeColorSchemes ();
return ret;
}
}
///
/// Contains a dictionary of the s for a Terminal.Gui application.
///
///
///
/// A Theme is a collection of settings that are named. The default theme is named "Default".
///
///
/// The property is used to detemrine the currently active theme.
///
///
///
/// is a singleton class. It is created when the first property is accessed.
/// Accessing is the same as accessing .
///
///
/// "Themes": [
/// {
/// "Default": {
/// "ColorSchemes": [
/// {
/// "TopLevel": {
/// "Normal": {
/// "Foreground": "BrightGreen",
/// "Background": "Black"
/// },
/// "Focus": {
/// "Foreground": "White",
/// "Background": "Cyan"
///
/// },
/// "HotNormal": {
/// "Foreground": "Brown",
/// "Background": "Black"
///
/// },
/// "HotFocus": {
/// "Foreground": "Blue",
/// "Background": "Cyan"
/// },
/// "Disabled": {
/// "Foreground": "DarkGray",
/// "Background": "Black"
///
/// }
/// }
/// }
///
public class ThemeManager : IDictionary {
private static readonly ThemeManager _instance = new ThemeManager ();
static ThemeManager () { } // Make sure it's truly lazy
private ThemeManager () { } // Prevent instantiation outside
///
/// Class is a singleton...
///
public static ThemeManager Instance { get { return _instance; } }
private static string theme = string.Empty;
///
/// The currently selected theme. This is the internal version; see .
///
[JsonInclude, SerializableConfigurationProperty (Scope = typeof (SettingsScope), OmitClassName = true), JsonPropertyName ("Theme")]
internal static string SelectedTheme {
get => theme;
set {
var oldTheme = theme;
theme = value;
if (oldTheme != theme &&
ConfigurationManager.Settings! ["Themes"]?.PropertyValue is Dictionary themes &&
themes.ContainsKey (theme)) {
ConfigurationManager.Settings! ["Theme"].PropertyValue = theme;
Instance.OnThemeChanged (oldTheme);
}
}
}
///
/// Gets or sets the currently selected theme. The value is persisted to the "Theme"
/// property.
///
[JsonIgnore]
public string Theme {
get => ThemeManager.SelectedTheme;
set {
ThemeManager.SelectedTheme = value;
}
}
///
/// Event arguments for the events.
///
public class ThemeManagerEventArgs : EventArgs {
///
/// The name of the new active theme..
///
public string NewTheme { get; set; } = string.Empty;
///
/// Initializes a new instance of
///
public ThemeManagerEventArgs (string newTheme)
{
NewTheme = newTheme;
}
}
///
/// Called when the selected theme has changed. Fires the event.
///
internal void OnThemeChanged (string theme)
{
Debug.WriteLine ($"Themes.OnThemeChanged({theme}) -> {Theme}");
ThemeChanged?.Invoke (new ThemeManagerEventArgs (theme));
}
///
/// Event fired he selected theme has changed.
/// application.
///
public event Action? ThemeChanged;
///
/// Holds the definitions.
///
[JsonInclude, JsonConverter (typeof (DictionaryJsonConverter))]
[SerializableConfigurationProperty (Scope = typeof (SettingsScope), OmitClassName = true)]
public static Dictionary? Themes {
get => Settings? ["Themes"]?.PropertyValue as Dictionary; // themes ?? new Dictionary ();
set {
//if (themes == null || value == null) {
// themes = value;
//} else {
// themes = (Dictionary)DeepMemberwiseCopy (value!, themes!)!;
//}
Settings! ["Themes"].PropertyValue = value;
}
}
internal static void Reset ()
{
Debug.WriteLine ($"Themes.Reset()");
Themes?.Clear ();
SelectedTheme = string.Empty;
}
internal static void GetHardCodedDefaults ()
{
Debug.WriteLine ($"Themes.GetHardCodedDefaults()");
var theme = new ThemeScope ();
theme.RetrieveValues ();
Themes = new Dictionary (StringComparer.InvariantCultureIgnoreCase) { { "Default", theme } };
SelectedTheme = "Default";
}
#region IDictionary
///
public ICollection Keys => ((IDictionary)Themes!).Keys;
///
public ICollection Values => ((IDictionary)Themes!).Values;
///
public int Count => ((ICollection>)Themes!).Count;
///
public bool IsReadOnly => ((ICollection>)Themes!).IsReadOnly;
///
public ThemeScope this [string key] { get => ((IDictionary)Themes!) [key]; set => ((IDictionary)Themes!) [key] = value; }
///
public void Add (string key, ThemeScope value)
{
((IDictionary)Themes!).Add (key, value);
}
///
public bool ContainsKey (string key)
{
return ((IDictionary)Themes!).ContainsKey (key);
}
///
public bool Remove (string key)
{
return ((IDictionary)Themes!).Remove (key);
}
///
public bool TryGetValue (string key, out ThemeScope value)
{
return ((IDictionary)Themes!).TryGetValue (key, out value!);
}
///
public void Add (KeyValuePair item)
{
((ICollection>)Themes!).Add (item);
}
///
public void Clear ()
{
((ICollection>)Themes!).Clear ();
}
///
public bool Contains (KeyValuePair item)
{
return ((ICollection>)Themes!).Contains (item);
}
///
public void CopyTo (KeyValuePair [] array, int arrayIndex)
{
((ICollection>)Themes!).CopyTo (array, arrayIndex);
}
///
public bool Remove (KeyValuePair item)
{
return ((ICollection>)Themes!).Remove (item);
}
///
public IEnumerator> GetEnumerator ()
{
return ((IEnumerable>)Themes!).GetEnumerator ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return ((IEnumerable)Themes!).GetEnumerator ();
}
#endregion
}
}
}