Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 86 additions & 45 deletions src/Eto/Forms/Key.cs
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


namespace Eto.Forms;

/// <summary>
Expand Down Expand Up @@ -281,19 +281,19 @@ public enum Keys

}

/// <summary>
/// Extensions for the <see cref="Keys"/> enumeration
/// </summary>
public static class KeysExtensions
{
static void AppendSeparator (StringBuilder sb, string separator, string value)
{
if (sb.Length > 0)
sb.Append (separator);
sb.Append (value);
}
/// <summary>
/// Extensions for the <see cref="Keys"/> enumeration
/// </summary>
public static class KeysExtensions
{
static void AppendSeparator(StringBuilder sb, string separator, string value)
{
if (sb.Length > 0)
sb.Append(separator);
sb.Append(value);
}

static readonly Dictionary<Keys, string> keymap = new Dictionary<Keys,string> {
static readonly Dictionary<Keys, string> keymap = new Dictionary<Keys, string> {
{ Keys.D0, "0" },
{ Keys.D1, "1" },
{ Keys.D2, "2" },
Expand Down Expand Up @@ -324,44 +324,85 @@ static void AppendSeparator (StringBuilder sb, string separator, string value)

{ Keys.Semicolon, ";" },
{ Keys.Quote, "'" },

{ Keys.Comma, "," },
{ Keys.Period, "." },
{ Keys.Slash, "/" },

{ Keys.RightBracket, "]" },
{ Keys.LeftBracket, "[" }
};

/// <summary>
/// Converts the specified key to a shortcut string such as Ctrl+Alt+Z
/// </summary>
/// <param name="key">Key to convert</param>
/// <param name="separator">Separator between each modifier and key</param>
/// <returns>A human-readable string representing the key combination including modifiers</returns>
public static string ToShortcutString(this Keys key, string separator = "+")
{
var sb = new StringBuilder();
if (key.HasFlag(Keys.Application))
AppendSeparator(sb, separator,
Application.Instance.Localize(key,
EtoEnvironment.Platform.IsMac ? "\x2318" :
EtoEnvironment.Platform.IsWindows ? "Win" :
"App"));
if (key.HasFlag(Keys.Control))
AppendSeparator(sb, separator, Application.Instance.Localize(key, EtoEnvironment.Platform.IsMac ? "^" : "Ctrl"));
if (key.HasFlag(Keys.Shift))
AppendSeparator(sb, separator, Application.Instance.Localize(key, EtoEnvironment.Platform.IsMac ? "\x21e7" : "Shift"));
if (key.HasFlag(Keys.Alt))
AppendSeparator(sb, separator, Application.Instance.Localize(key, EtoEnvironment.Platform.IsMac ? "\x2325" : "Alt"));
static readonly Dictionary<string, Keys> reverseKeymap = keymap
.GroupBy(kvp => kvp.Value)
.ToDictionary(g => g.Key, g => g.First().Key); // skip dupes, and take first value.

var mainKey = key & Keys.KeyMask;
string val;
if (keymap.TryGetValue(mainKey, out val))
AppendSeparator(sb, separator, val);
else if (mainKey != Keys.None)
AppendSeparator(sb, separator, mainKey.ToString());
/// <summary>
/// Converts the specified key to a shortcut string such as Ctrl+Alt+Z
/// </summary>
/// <param name="key">Key to convert</param>
/// <param name="separator">Separator between each modifier and key</param>
/// <returns>A human-readable string representing the key combination including modifiers</returns>
public static string ToShortcutString(this Keys key, string separator = "+")
{
var sb = new StringBuilder();
if (key.HasFlag(Keys.Application))
AppendSeparator(sb, separator,
Application.Instance.Localize(key,
EtoEnvironment.Platform.IsMac ? "\x2318" :
EtoEnvironment.Platform.IsWindows ? "Win" :
"App"));
if (key.HasFlag(Keys.Control))
AppendSeparator(sb, separator, Application.Instance.Localize(key, EtoEnvironment.Platform.IsMac ? "^" : "Ctrl"));
if (key.HasFlag(Keys.Shift))
AppendSeparator(sb, separator, Application.Instance.Localize(key, EtoEnvironment.Platform.IsMac ? "\x21e7" : "Shift"));
if (key.HasFlag(Keys.Alt))
AppendSeparator(sb, separator, Application.Instance.Localize(key, EtoEnvironment.Platform.IsMac ? "\x2325" : "Alt"));

return sb.ToString();
}
}
var mainKey = key & Keys.KeyMask;
string val;
if (keymap.TryGetValue(mainKey, out val))
AppendSeparator(sb, separator, val);
else if (mainKey != Keys.None)
AppendSeparator(sb, separator, mainKey.ToString());

return sb.ToString();
}

/// <summary>
/// Parses a shortcut string such as "Ctrl+Alt+Z" into a <see cref="Keys"/> value
/// </summary>
/// <param name="shortcutString">The shortcut string to parse</param>
/// <returns>The key equivalent, or Keys.None if not found</returns>
public static Keys FromShortcutString(string shortcutString)
{
if (string.IsNullOrEmpty(shortcutString))
return Keys.None;
var parts = shortcutString.Split(new[] { '+', '-', '|' }, StringSplitOptions.RemoveEmptyEntries);
Keys keys = Keys.None;
foreach (var part in parts)
{
var trimmedPart = part.Trim();
if (reverseKeymap.TryGetValue(trimmedPart, out var mappedKey))
keys |= mappedKey;
else if (Enum.TryParse<Keys>(trimmedPart, true, out var key))
keys |= key;
else keys |= trimmedPart.ToLowerInvariant() switch
{
"commonmodifier" => Application.Instance.CommonModifier,
"alternatemodifier" => Application.Instance.AlternateModifier,
"\x2325" => Keys.Alt,
"alt" => Keys.Alt,
"\x21e7" => Keys.Shift,
"shift" => Keys.Shift,
"^" => Keys.Control,
"ctrl" => Keys.Control,
"\x2318" => Keys.Application,
"win" => Keys.Application,
"app" => Keys.Application,
_ => Keys.None,
};
}
return keys;
}
}
29 changes: 5 additions & 24 deletions src/Eto/Forms/KeysConverter.cs
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
namespace Eto.Forms;
namespace Eto.Forms;

class KeysConverter : sc.TypeConverter
{
public string[] Separators { get; set; }

public KeysConverter()
{
Separators = new [] { "+", ",", "|" };
}

public override bool CanConvertFrom(sc.ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
Expand All @@ -21,30 +14,18 @@ public override bool CanConvertTo(sc.ITypeDescriptorContext context, Type destin

public override object ConvertFrom(sc.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
var text = value as string;
if (text != null)
if (value is string text)
{
var keys = text.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
Keys result = Keys.None;
foreach (var key in keys)
{
if (key == "CommonModifier")
result |= Application.Instance.CommonModifier;
else if (key == "AlternateModifier")
result |= Application.Instance.AlternateModifier;
else
result |= (Keys)Enum.Parse(typeof(Keys), key);
}
return result;
return KeysExtensions.FromShortcutString(text);
}
return base.ConvertFrom(context, culture, value);
}

public override object ConvertTo(sc.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value is Keys)
if (destinationType == typeof(string) && value is Keys keys)
{
return ((Keys)value).ToShortcutString(Separators.First());
return keys.ToShortcutString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
Expand Down
Loading