KeyCodeJsonConverter.cs 6.0 KB

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