KeyCodeJsonConverter.cs 5.9 KB

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