-If you combine `OneWay` and `OneWayToSource` data bindings, you get `TwoWay` data binding. Also be sure to use the `ustring` type instead of the `string` type. Invoking commands should be as simple as this:
+If you combine `OneWay` and `OneWayToSource` data bindings, you get `TwoWay` data binding. Also be sure to use the `string` type instead of the `string` type. Invoking commands should be as simple as this:
/// If <see langword="true"/>, forces the use of the System.Console-based (see <see cref="NetDriver"/>) driver. The default is <see langword="false"/>.
/// If <see langword="true"/>, forces the use of the System.Console-based (see <see cref="NetDriver"/>) driver. The default is <see langword="false"/>.
+ 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}.");
- 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>
+ /// 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>).
+ /// The values are instances of <see cref="ConfigProperty"/> which hold the property's value and the
+ /// <see cref="PropertyInfo"/> that allows <see cref="ConfigurationManager"/> to get and set the property's value.
+ /// </summary>
+ /// <remarks>
+ /// Is <see langword="null"/> until <see cref="Initialize"/> is called.
- /// 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>
+ /// The backing property for <see cref="Settings"/>.
+ /// </summary>
+ /// <remarks>
+ /// Is <see langword="null"/> until <see cref="Reset"/> is called. Gets set to a new instance by
+ /// deserialization (see <see cref="Load"/>).
+ /// </remarks>
+ private static SettingsScope? _settings;
- /// <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;
- }
+ /// <summary>
+ /// The root object of Terminal.Gui configuration settings / JSON schema. Contains only properties with the <see cref="SettingsScope"/>
+ /// attribute value.
+ /// </summary>
+ public static SettingsScope? Settings {
+ get {
+ if (_settings == null) {
+ throw new InvalidOperationException ("ConfigurationManager has not been initialized. Call ConfigurationManager.Reset() before accessing the Settings property.");
+ /// The root object of Terminal.Gui themes manager. Contains only properties with the <see cref="ThemeScope"/>
+ /// attribute value.
+ /// </summary>
+ public static ThemeManager? Themes => ThemeManager.Instance;
- 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}.");
+ Dictionary<string, Type> classesWithConfigProps = new Dictionary<string, Type> (StringComparer.InvariantCultureIgnoreCase);
+ // Get Terminal.Gui.dll classes
- /// <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>).
- /// The values are instances of <see cref="ConfigProperty"/> which hold the property's value and the
- /// <see cref="PropertyInfo"/> that allows <see cref="ConfigurationManager"/> to get and set the property's value.
- /// </summary>
- /// <remarks>
- /// Is <see langword="null"/> until <see cref="Initialize"/> is called.
- /// The root object of Terminal.Gui configuration settings / JSON schema. Contains only properties with the <see cref="SettingsScope"/>
- /// attribute value.
- /// </summary>
- public static SettingsScope? Settings {
- get {
- if (_settings == null) {
- throw new InvalidOperationException ("ConfigurationManager has not been initialized. Call ConfigurationManager.Reset() before accessing the Settings property.");
+ Debug.WriteLine ($"ConfigManager.getConfigProperties found {classesWithConfigProps.Count} classes:");
+ throw new Exception ($"Property {p.Name} in class {p.DeclaringType?.Name} is not static. All SerializableConfigurationProperty properties must be static.");
}
}
- return _settings;
- }
- set {
- _settings = value!;
}
}
}
}
- /// <summary>
- /// The root object of Terminal.Gui themes manager. Contains only properties with the <see cref="ThemeScope"/>
- /// attribute value.
- /// </summary>
- public static ThemeManager? Themes => ThemeManager.Instance;
- throw new Exception ($"Property {p.Name} in class {p.DeclaringType?.Name} is not static. All SerializableConfigurationProperty properties must be static.");
- }
- }
- }
+ /// <summary>
+ /// Gets or sets whether the <see cref="ConfigurationManager"/> should throw an exception if it encounters
+ /// an error on deserialization. If <see langword="false"/> (the default), the error is logged and printed to the
+ /// console when <see cref="Application.Shutdown"/> is called.
+ public static Dictionary<string, ThemeScope>? Themes {
+ get => ConfigurationManager.Settings? ["Themes"]?.PropertyValue as Dictionary<string, ThemeScope>; // themes ?? new Dictionary<string, ThemeScope> ();
+ public ICollection<string> Keys => ((IDictionary<string, ThemeScope>)Themes!).Keys;
+ public ICollection<ThemeScope> Values => ((IDictionary<string, ThemeScope>)Themes!).Values;
+ public int Count => ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).Count;
+ public bool IsReadOnly => ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).IsReadOnly;
+ public ThemeScope this [string key] { get => ((IDictionary<string, ThemeScope>)Themes!) [key]; set => ((IDictionary<string, ThemeScope>)Themes!) [key] = value; }
- public ICollection<string> Keys => ((IDictionary<string, ThemeScope>)Themes!).Keys;
- /// <inheritdoc/>
- public ICollection<ThemeScope> Values => ((IDictionary<string, ThemeScope>)Themes!).Values;
- /// <inheritdoc/>
- public int Count => ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).Count;
- /// <inheritdoc/>
- public bool IsReadOnly => ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).IsReadOnly;
- /// <inheritdoc/>
- public ThemeScope this [string key] { get => ((IDictionary<string, ThemeScope>)Themes!) [key]; set => ((IDictionary<string, ThemeScope>)Themes!) [key] = value; }
public static Dictionary<string, ColorScheme> ColorSchemes { get; private set; }
public static Dictionary<string, ColorScheme> ColorSchemes { get; private set; }
}
}
@@ -659,12 +679,13 @@ namespace Terminal.Gui {
/// <remarks>Works under Xterm-like terminal otherwise this is equivalent to <see ref="Block"/></remarks>
/// <remarks>Works under Xterm-like terminal otherwise this is equivalent to <see ref="Block"/></remarks>
BoxFix = 0x02020164,
BoxFix = 0x02020164,
}
}
-
+
/// <summary>
/// <summary>
/// ConsoleDriver is an abstract class that defines the requirements for a console driver.
/// ConsoleDriver is an abstract class that defines the requirements for a console driver.
/// There are currently three implementations: <see cref="CursesDriver"/> (for Unix and Mac), <see cref="WindowsDriver"/>, and <see cref="NetDriver"/> that uses the .NET Console API.
/// There are currently three implementations: <see cref="CursesDriver"/> (for Unix and Mac), <see cref="WindowsDriver"/>, and <see cref="NetDriver"/> that uses the .NET Console API.
/// </summary>
/// </summary>
public abstract class ConsoleDriver {
public abstract class ConsoleDriver {
+
/// <summary>
/// <summary>
/// The handler fired when the terminal is resized.
/// The handler fired when the terminal is resized.
/// </summary>
/// </summary>
@@ -731,28 +752,25 @@ namespace Terminal.Gui {
public abstract void Move (int col, int row);
public abstract void Move (int col, int row);
/// <summary>
/// <summary>
- /// Adds the specified rune to the display at the current cursor position.
+ /// Tests if the specified rune is supported by the driver.
/// </summary>
/// </summary>
- /// <param name="rune">Rune to add.</param>
- public abstract void AddRune (Rune rune);
-
- /// <summary>
- /// Ensures a Rune is not a control character and can be displayed by translating characters below 0x20
- /// to equivalent, printable, Unicode chars.
- /// </summary>
- /// <param name="c">Rune to translate</param>
- /// <returns></returns>
- public static Rune MakePrintable (Rune c)
+ /// <param name="rune"></param>
+ /// <returns><see langword="true"/> if the rune can be properly presented; <see langword="false"/> if the driver
+ /// does not support displaying this rune.</returns>
+ public virtual bool IsRuneSupported (Rune rune)
{
{
- if (c <= 0x1F || (c >= 0X7F && c <= 0x9F)) {
- // ASCII (C0) control characters.
- // C1 control characters (https://www.aivosto.com/articles/control-characters.html#c1)
- return new Rune (c + 0x2400);
+ if (rune.Value > RuneExtensions.MaxUnicodeCodePoint) {
+ return false;
}
}
-
- return c;
+ return true;
}
}
-
+
+ /// <summary>
+ /// Adds the specified rune to the display at the current cursor position.
+ /// </summary>
+ /// <param name="rune">Rune to add.</param>
+ public abstract void AddRune (Rune rune);
+
/// <summary>
/// <summary>
/// Ensures that the column and line are in a valid range from the size of the driver.
/// Ensures that the column and line are in a valid range from the size of the driver.
/// </summary>
/// </summary>
@@ -767,7 +785,7 @@ namespace Terminal.Gui {
/// Adds the <paramref name="str"/> to the display at the cursor position.
/// Adds the <paramref name="str"/> to the display at the cursor position.
/// </summary>
/// </summary>
/// <param name="str">String.</param>
/// <param name="str">String.</param>
- public abstract void AddStr (ustring str);
+ public abstract void AddStr (string str);
/// <summary>
/// <summary>
/// Prepare the driver and set the key and mouse events handlers.
/// Prepare the driver and set the key and mouse events handlers.
- /// Gets the total width of the left and right sides of the rectangle. Sets the height of the left and right sides of the rectangle to half the specified value.
+ /// Gets the total height of the top and bottom sides of the rectangle. Sets the height of the top and bottom sides of the rectangle to half the specified value.
/// </summary>
/// </summary>
public int Vertical {
public int Vertical {
get {
get {
@@ -94,7 +93,7 @@ namespace Terminal.Gui {
}
}
/// <summary>
/// <summary>
- /// Gets the total width of the top and bottom sides of the rectangle. Sets the width of the top and bottom sides of the rectangle to half the specified value.
+ /// Gets the total width of the left and right sides of the rectangle. Sets the width of the left and rigth sides of the rectangle to half the specified value.
/// </summary>
/// </summary>
public int Horizontal {
public int Horizontal {
get {
get {
@@ -143,19 +142,19 @@ namespace Terminal.Gui {
return Rect.Empty;
return Rect.Empty;
}
}
- System.Rune clearChar = ' ';
- System.Rune leftChar = clearChar;
- System.Rune rightChar = clearChar;
- System.Rune topChar = clearChar;
- System.Rune bottomChar = clearChar;
+ Rune clearChar = (Rune)' ';
+ Rune leftChar = clearChar;
+ Rune rightChar = clearChar;
+ Rune topChar = clearChar;
+ Rune bottomChar = clearChar;
if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FramePadding) == ConsoleDriver.DiagnosticFlags.FramePadding) {
if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FramePadding) == ConsoleDriver.DiagnosticFlags.FramePadding) {