using System; using System.ComponentModel; using System.Text; using System.Windows.Input; namespace ICSharpCode.Core.Presentation { /// /// Describes full key gesture or part of a key gesture /// /// This class is is designed to react to key events even it descibes only part of them /// For example if event argument holds modifiers Ctrl, Shift and key C then partial template /// with single modifier Ctrl and a key C will match this event /// [TypeConverter(typeof(PartialKeyGestureConverter))] public class PartialKeyGesture : KeyGesture { private readonly Key _key; private readonly ModifierKeys _modifiers; /// /// Key associated with partial key gesture /// public new Key Key { get { return _key; } } /// /// Modifier keys associated with partial key gesture /// public new ModifierKeys Modifiers { get { return _modifiers; } } /// /// Create new instance of from /// /// Arguments generated by key event public PartialKeyGesture(KeyEventArgs keyEventArgs) : base(Key.None, ModifierKeys.None) { var keyboardDevice = (KeyboardDevice)keyEventArgs.Device; var enteredKey = keyEventArgs.Key == Key.System ? keyEventArgs.SystemKey : keyEventArgs.Key; var enteredModifiers = keyboardDevice.Modifiers; if(Array.IndexOf(new[] { Key.LeftAlt, Key.RightAlt, Key.LeftShift, Key.RightShift, Key.LeftCtrl, Key.RightCtrl, Key.LWin, Key.RWin}, enteredKey) >= 0) { _key = Key.None; _modifiers = enteredModifiers; } else { _key = enteredKey; _modifiers = enteredModifiers; } } /// /// Create new instance of from /// /// Key gesture public PartialKeyGesture(KeyGesture gesture) : base(Key.None, ModifierKeys.None) { var partialKeyGesture = gesture as PartialKeyGesture; if (partialKeyGesture != null) { _key = partialKeyGesture.Key; _modifiers = partialKeyGesture.Modifiers; } else if (gesture is MultiKeyGesture) { throw new ArgumentException("Can not create partial key gesture from multi-key gesture"); } else { _key = gesture.Key; _modifiers = gesture.Modifiers; } } /// /// Create new instance of having key and modifiers /// /// The key associated with partial key gesture /// Modifier keys associated with partial key gesture public PartialKeyGesture(Key key, ModifierKeys modifiers) : base(Key.None, ModifierKeys.None) { _key = key; _modifiers = modifiers; } /// /// Create new instance of having only key and no modifiers /// /// The key associated with partial key gesture public PartialKeyGesture(Key key) : base(Key.None, ModifierKeys.None) { _key = key; _modifiers = ModifierKeys.None; } /// /// Create new instance of having only key and no modifiers /// /// Modifier keys associated with partial key gesture public PartialKeyGesture(ModifierKeys modifiers) : base(Key.None, ModifierKeys.None) { _key = Key.None; _modifiers = modifiers; } /// /// Determines whether key gesture strictly matches this key gesture template /// (That is key and modifier both match key event arguments) /// /// The target /// Input event arguments /// True if the event data matches this ; otherwise, false. public bool StrictlyMatches(object targetElement, InputEventArgs args) { var keyEventArgs = args as KeyEventArgs; if(keyEventArgs == null) { return false; } var keyboard = (KeyboardDevice)keyEventArgs.Device; // If system key is pressed if (keyEventArgs.Key == Key.System) { return keyboard.Modifiers == Modifiers && keyEventArgs.SystemKey == Key; } return keyboard.Modifiers == Modifiers && keyEventArgs.Key == Key; } /// /// Determines whether key event arguments matches this instance of /// /// The target /// Input event arguments /// True if event data matches parial event arguments otherwise false public override bool Matches(object targetElement, InputEventArgs inputEventArgs) { var keyEventArgs = inputEventArgs as KeyEventArgs; if(keyEventArgs == null) { return false; } var keyboard = (KeyboardDevice)keyEventArgs.Device; // When system key (Alt) is pressed real key is moved to SystemKey property var enteredKey = keyEventArgs.Key == Key.System ? keyEventArgs.SystemKey : keyEventArgs.Key; var keyMatches = Key == enteredKey; // Determine whether template contains only part of modifier keys contained in // gesture. For example if template contains Control modifier, but gesture contains // Control and Alt true will be returned var modifierMatches = keyboard.Modifiers - (keyboard.Modifiers ^ Modifiers) >= 0; // Template contains no modifiers compare only keys if (Modifiers == ModifierKeys.None) { return keyMatches; } // If template has modifiers but key is one of modifier keys return true if // modifiers match. This is used because when user presses modifier key it is // presented in Key property and Modifiers property if (Array.IndexOf(new[] { Key.LeftAlt, Key.RightAlt, Key.LeftShift, Key.RightShift, Key.LeftCtrl, Key.RightCtrl, Key.LWin, Key.RWin, Key.System}, enteredKey) >= 0) { return modifierMatches; } return modifierMatches && keyMatches; } /// /// Returns string that represents /// /// String public override string ToString() { var pressedButton = new StringBuilder(); if (Modifiers != ModifierKeys.None) { pressedButton.AppendFormat("{0}+", new ModifierKeysConverter().ConvertToInvariantString(Modifiers)); } // Filter modifier keys from being displayed twice (example: Ctrl + LeftCtrl) if (Array.IndexOf(new[] { Key.LeftAlt, Key.RightAlt, Key.LeftShift, Key.RightShift, Key.LeftCtrl, Key.RightCtrl, Key.LWin, Key.RWin, Key.System}, Key) < 0) { pressedButton.Append(new KeyConverter().ConvertToInvariantString(Key)); } return pressedButton.ToString(); } } }