KeyJsonConverter.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text.Json;
  4. using System.Text.Json.Serialization;
  5. namespace Terminal.Gui {
  6. /// <summary>
  7. /// Json converter for the <see cref="Key"/> class.
  8. /// </summary>
  9. public class KeyJsonConverter : JsonConverter<Key> {
  10. /// <inheritdoc/>
  11. public override Key Read (ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
  12. {
  13. if (reader.TokenType == JsonTokenType.StartObject) {
  14. Key key = Key.Unknown;
  15. Dictionary<string, Key> modifierDict = new Dictionary<string, Key> (comparer: StringComparer.InvariantCultureIgnoreCase) {
  16. { "Shift", Key.ShiftMask },
  17. { "Ctrl", Key.CtrlMask },
  18. { "Alt", Key.AltMask }
  19. };
  20. List<Key> modifiers = new List<Key> ();
  21. while (reader.Read ()) {
  22. if (reader.TokenType == JsonTokenType.EndObject) {
  23. break;
  24. }
  25. if (reader.TokenType == JsonTokenType.PropertyName) {
  26. string propertyName = reader.GetString ();
  27. reader.Read ();
  28. switch (propertyName.ToLowerInvariant ()) {
  29. case "key":
  30. if (reader.TokenType == JsonTokenType.String) {
  31. if (Enum.TryParse (reader.GetString (), false, out key)) {
  32. break;
  33. }
  34. // The enum uses "D0..D9" for the number keys
  35. if (Enum.TryParse (reader.GetString ().TrimStart ('D', 'd'), false, out key)) {
  36. break;
  37. }
  38. if (key == Key.Unknown || key == Key.Null) {
  39. throw new JsonException ($"The value \"{reader.GetString ()}\" is not a valid Key.");
  40. }
  41. } else if (reader.TokenType == JsonTokenType.Number) {
  42. try {
  43. key = (Key)reader.GetInt32 ();
  44. } catch (InvalidOperationException ioe) {
  45. throw new JsonException ($"Error parsing Key value: {ioe.Message}", ioe);
  46. } catch (FormatException ioe) {
  47. throw new JsonException ($"Error parsing Key value: {ioe.Message}", ioe);
  48. }
  49. break;
  50. }
  51. break;
  52. case "modifiers":
  53. if (reader.TokenType == JsonTokenType.StartArray) {
  54. while (reader.Read ()) {
  55. if (reader.TokenType == JsonTokenType.EndArray) {
  56. break;
  57. }
  58. var mod = reader.GetString ();
  59. try {
  60. modifiers.Add (modifierDict [mod]);
  61. } catch (KeyNotFoundException e) {
  62. throw new JsonException ($"The value \"{mod}\" is not a valid modifier.", e);
  63. }
  64. }
  65. } else {
  66. throw new JsonException ($"Expected an array of modifiers, but got \"{reader.TokenType}\".");
  67. }
  68. break;
  69. default:
  70. throw new JsonException ($"Unexpected Key property \"{propertyName}\".");
  71. }
  72. }
  73. }
  74. foreach (var modifier in modifiers) {
  75. key |= modifier;
  76. }
  77. return key;
  78. }
  79. throw new JsonException ($"Unexpected StartObject token when parsing Key: {reader.TokenType}.");
  80. }
  81. /// <inheritdoc/>
  82. public override void Write (Utf8JsonWriter writer, Key value, JsonSerializerOptions options)
  83. {
  84. writer.WriteStartObject ();
  85. var keyName = (value & ~Key.CtrlMask & ~Key.ShiftMask & ~Key.AltMask).ToString ();
  86. if (keyName != null) {
  87. writer.WriteString ("Key", keyName);
  88. } else {
  89. writer.WriteNumber ("Key", (uint)(value & ~Key.CtrlMask & ~Key.ShiftMask & ~Key.AltMask));
  90. }
  91. Dictionary<string, Key> modifierDict = new Dictionary<string, Key>
  92. {
  93. { "Shift", Key.ShiftMask },
  94. { "Ctrl", Key.CtrlMask },
  95. { "Alt", Key.AltMask }
  96. };
  97. List<string> modifiers = new List<string> ();
  98. foreach (var pair in modifierDict) {
  99. if ((value & pair.Value) == pair.Value) {
  100. modifiers.Add (pair.Key);
  101. }
  102. }
  103. if (modifiers.Count > 0) {
  104. writer.WritePropertyName ("Modifiers");
  105. writer.WriteStartArray ();
  106. foreach (var modifier in modifiers) {
  107. writer.WriteStringValue (modifier);
  108. }
  109. writer.WriteEndArray ();
  110. }
  111. writer.WriteEndObject ();
  112. }
  113. }
  114. }