/************************************************************************ Extended WPF Toolkit Copyright (C) 2010-2012 Xceed Software Inc. This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license This program can be provided to you by Xceed Software Inc. under a proprietary commercial license agreement for use in non-Open Source projects. The commercial version of Extended WPF Toolkit also includes priority technical support, commercial updates, and many additional useful WPF controls if you license Xceed Business Suite for WPF. Visit http://xceed.com and follow @datagrid on Twitter. **********************************************************************/ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows.Input; namespace Xceed.Wpf.Toolkit.Core.Input { [TypeConverter( typeof( KeyModifierCollectionConverter ) )] public class KeyModifierCollection : Collection { #region AreActive Property public bool AreActive { get { if( this.Count == 0 ) return true; // if the Blocked modifier is present, then the action is not allowed // so simply return false if( this.Contains( KeyModifier.Blocked ) ) return false; if( this.Contains( KeyModifier.Exact ) ) return this.IsExactMatch(); return this.MatchAny(); } } #endregion private static bool IsKeyPressed( KeyModifier modifier, ICollection keys ) { switch( modifier ) { case KeyModifier.Alt: return keys.Contains( Key.LeftAlt ) || keys.Contains( Key.RightAlt ); case KeyModifier.LeftAlt: return keys.Contains( Key.LeftAlt ); case KeyModifier.RightAlt: return keys.Contains( Key.RightAlt ); case KeyModifier.Ctrl: return keys.Contains( Key.LeftCtrl ) || keys.Contains( Key.RightCtrl ); case KeyModifier.LeftCtrl: return keys.Contains( Key.LeftCtrl ); case KeyModifier.RightCtrl: return keys.Contains( Key.RightCtrl ); case KeyModifier.Shift: return keys.Contains( Key.LeftShift ) || keys.Contains( Key.RightShift ); case KeyModifier.LeftShift: return keys.Contains( Key.LeftShift ); case KeyModifier.RightShift: return keys.Contains( Key.RightShift ); case KeyModifier.None: return true; default: throw new NotSupportedException( "Unknown modifier" ); } } private static bool HasModifier( Key key, ICollection modifiers ) { switch( key ) { case Key.LeftAlt: return modifiers.Contains( KeyModifier.Alt ) || modifiers.Contains( KeyModifier.LeftAlt ); case Key.RightAlt: return modifiers.Contains( KeyModifier.Alt ) || modifiers.Contains( KeyModifier.RightAlt ); case Key.LeftCtrl: return modifiers.Contains( KeyModifier.Ctrl ) || modifiers.Contains( KeyModifier.LeftCtrl ); case Key.RightCtrl: return modifiers.Contains( KeyModifier.Ctrl ) || modifiers.Contains( KeyModifier.RightCtrl ); case Key.LeftShift: return modifiers.Contains( KeyModifier.Shift ) || modifiers.Contains( KeyModifier.LeftShift ); case Key.RightShift: return modifiers.Contains( KeyModifier.Shift ) || modifiers.Contains( KeyModifier.RightShift ); default: throw new NotSupportedException( "Unknown key" ); } } private bool IsExactMatch() { HashSet modifiers = this.GetKeyModifiers(); HashSet keys = this.GetKeysPressed(); // No key must be pressed for the modifier None. if( this.Contains( KeyModifier.None ) ) return ( modifiers.Count == 0 ) && ( keys.Count == 0 ); // Make sure every modifier has a matching key pressed. foreach( KeyModifier modifier in modifiers ) { if( !KeyModifierCollection.IsKeyPressed( modifier, keys ) ) return false; } // Make sure every key pressed has a matching modifier. foreach( Key key in keys ) { if( !KeyModifierCollection.HasModifier( key, modifiers ) ) return false; } return true; } private bool MatchAny() { if( this.Contains( KeyModifier.None ) ) return true; HashSet modifiers = this.GetKeyModifiers(); HashSet keys = this.GetKeysPressed(); foreach( KeyModifier modifier in modifiers ) { if( KeyModifierCollection.IsKeyPressed( modifier, keys ) ) return true; } return false; } private HashSet GetKeyModifiers() { HashSet modifiers = new HashSet(); foreach( KeyModifier modifier in this ) { switch( modifier ) { case KeyModifier.Alt: case KeyModifier.LeftAlt: case KeyModifier.RightAlt: case KeyModifier.Ctrl: case KeyModifier.LeftCtrl: case KeyModifier.RightCtrl: case KeyModifier.Shift: case KeyModifier.LeftShift: case KeyModifier.RightShift: { if( !modifiers.Contains( modifier ) ) { modifiers.Add( modifier ); } } break; default: break; } } return modifiers; } private HashSet GetKeysPressed() { HashSet keys = new HashSet(); if( Keyboard.IsKeyDown( Key.LeftAlt ) ) keys.Add( Key.LeftAlt ); if( Keyboard.IsKeyDown( Key.RightAlt ) ) keys.Add( Key.RightAlt ); if( Keyboard.IsKeyDown( Key.LeftCtrl ) ) keys.Add( Key.LeftCtrl ); if( Keyboard.IsKeyDown( Key.RightCtrl ) ) keys.Add( Key.RightCtrl ); if( Keyboard.IsKeyDown( Key.LeftShift ) ) keys.Add( Key.LeftShift ); if( Keyboard.IsKeyDown( Key.RightShift ) ) keys.Add( Key.RightShift ); return keys; } } }