From 17374b13d4c143ea5a760630d67e3b86669d5000 Mon Sep 17 00:00:00 2001 From: Sergej Andrejev Date: Sat, 20 Jun 2009 10:09:59 +0000 Subject: [PATCH] MultiKeyGesture management in shortcut management add-in git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/shortcuts@4331 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../ShortcutsManagement.suo | Bin 93696 -> 96768 bytes .../Resources/StringResources.resx | 27 ++ .../ShortcutsManagement/Resources/Thumbs.db | Bin 9216 -> 16896 bytes .../Resources/block_small.png | Bin 0 -> 3662 bytes .../Resources/delete_small.png | Bin 0 -> 3270 bytes .../Resources/info_small.png | Bin 0 -> 3486 bytes .../Resources/plus_small.png | Bin 0 -> 3174 bytes .../Resources/search_small.png | Bin 0 -> 3466 bytes .../Resources/tick_small.png | Bin 0 -> 3141 bytes .../Resources/warning_small.png | Bin 0 -> 3235 bytes .../ShortcutsManagement.addin | 2 +- .../ShortcutsManagement.csproj | 19 +- .../Converters/BoolToVisibilityConverter.cs | 4 +- .../Converters/GesturesCollectionConverter.cs | 2 +- .../Src/Converters/InputGestureConverter.cs | 6 + .../ShortcutsManagement/Src/Data/AddIn.cs | 36 ++- .../Src/Data/GestureFilterMode.cs | 29 ++ .../Src/Data/IShortcutTreeEntry.cs | 17 +- .../Src/Data/KeyGestureTemplate.cs | 163 ---------- .../ShortcutsManagement/Src/Data/Shortcut.cs | 41 ++- .../Src/Data/ShortcutCategory.cs | 40 ++- .../Src/Data/ShortcutsFinder.cs | 60 ++-- .../Src/Dialogs/MultiKeyGestureTextBox.xaml | 92 ++++++ .../Dialogs/MultiKeyGestureTextBox.xaml.cs | 305 ++++++++++++++++++ .../Src/Dialogs/Resources.xaml | 5 +- .../Src/Dialogs/ShortcutManagementWindow.xaml | 25 +- .../Dialogs/ShortcutManagementWindow.xaml.cs | 106 +++--- .../ShortcutsManagementOptionsPanel.xaml | 2 +- .../ShortcutsManagementOptionsPanel.xaml.cs | 2 +- .../Src/Dialogs/ShortcutsTreeView.xaml | 18 +- .../Src/Dialogs/ShortcutsTreeView.xaml.cs | 126 ++++---- .../Extensions/PartialKeyGestureExtensions.cs | 140 ++++++++ .../Src/Extensions/TextBlockBehavior.cs | 2 +- .../Src/Extensions/TreeViewExtensions.cs | 4 +- .../ShortcutsManagement/Window1.xaml | 5 +- .../ShortcutsManagement/Window1.xaml.cs | 3 +- 36 files changed, 911 insertions(+), 370 deletions(-) create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/block_small.png create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/delete_small.png create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/info_small.png create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/plus_small.png create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/search_small.png create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/tick_small.png create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/warning_small.png create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/GestureFilterMode.cs delete mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/KeyGestureTemplate.cs create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml.cs create mode 100644 src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Extensions/PartialKeyGestureExtensions.cs diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement.suo b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement.suo index 8e19d5a96093d47c19b8025295423c7cdc649595..ac06e9d1f008f11f8d97b0ace5c6f1aac670325c 100644 GIT binary patch delta 8546 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 delta 6867 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 ME+a= Uncategorized + + First chord must have a modifier + + + Valid gesture + + + Multi key gesture is not finished + + + Invalid gesture. Sequence is not coherent. + + + Time given for gesture entry expired + + + Failed to add a gesture. First chord should contain a modifier + + + Failed to add a gesture. Gesture is unfinished. Last chord should have a key + + + Failed to add a gesture. Gesture must have atleast one chord + + + Gesture added + \ No newline at end of file diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/Thumbs.db b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/Thumbs.db index 935d92f604fba8a65b1f777cf000b098c53b7f3f..b3cac4ddc5a6a2b2310817411a042fc041e64efa 100644 GIT binary patch delta 2556 zcmZ|Q2~<=5=Ps4QB9Qt~8E zb_>d?2tig6Fa)Ifh?d79paBAEk=3wDFz+8A@4VB~-gCY)cjnF{cV_ zk588oGm@0T3D6=A1n)*A%g2d7My+re!`lW?$qL_zi9t=!g+8YsOT?w7RejagKhO)+kOl~%ZSz( ziybpV%jgMD++pk2m+_DN1zRabx0VeeP)uBx;)6!`m~y+@LQ+u`Bk*%8?@qOQ6X!y9 zMz3CU72{df&9JZAW-OY>c_x#6GIr2uc9|EnUnE938IQ0;#wpU~nwG@}z07YF==Rme zPbQ2gg-j-=#F0COx_J1|q)j_XHrKJXCY@pB+|!skC{@M@4^BQXIyxlxTyl}QC7PQe z*Jn~lALCJ;EuWuUEq96hq%lfao9s?XCd}$GxB}upJV*eE;3~KVegsM2I!Fd6UVnlz z75og+02TZb+yLo-2L1(Zf((GhR705!azHM~L*ai5Zhiszpa9$kcR(R10%%|fl%=2y z+y(bQIk*ohKqa7qD)0cHF*Q&!K^>?E4d5YY1dl)yXvQFYw7|_{zyPfP4gU1A{d;Q+ zGlDAm{ILJ9E}(r6!p>u7ut3ZWQo^6_{d%mR$j8P6ai9xv5J;eW+~G9KY`;2xxW_pA z3mI9n{^itx@m)9bst%1g7->uFZ~ijS*806m>56Gs{;{-A?=5OQ3%dIIUiG){Q{2Nm z_5BO$x1L=2_;%lvO$^G7Y(dXG8GJjy3HAL-eCVzOY6ncp$0s47v1AHUNhp4u^YBHc4KLF7eY zd3}{rbps!}Iegmxc*oh*w|5#Ic&w61{Fi7-a0w>0NTC0!0kd+Dl=eT+E~;LdN$(wK z{W#iFAH>I6D_drRLmIcyimu7zjkmwsmjPdx!jcm+L%PO{mN=!SN6wD%Dc7n9a(_$P zX}2#RCvwh|V_rD?Z$d9aMfYB&du@Vn8>f4q)L>Ctd$v5AF)|xA`1hhtYN3kXYrjeJ zAN5Nf6tD|?BE<%b2D8i7gW1fw(i!a%8IrXdBJh=x*G(4DlNy0G1X47auz=#YYlSvxwUilJh%(aliM4M&fK|F4@! zEmU-bsG3?wB+)a$1=(j;rFbMx`B=^Up(keF61A1~ZP+!Q;m}bDj~cd|4_9K|jis%| z&GN;ZG-p;gBDaTRlm?!?zD*)te2l#t_|hdXo* z>hr|A16P{#Az%cnxnm>#xg3o)mP(ZVQt`!J$0UtJ!pQ4awr&rTk|$i%tjtJ>DS4xX zEv)1mqov$g$FaLUo9(0(n9PO%^{kTyL|{SC}SDch{fJ6>aihZ{Zm%bq5$%mzKvpBZ$JiXfp`ou#~;s?J}qThqH}UVm;3+4qg`7|2a1+Yij}5W~SY0 z)-~2x{p(&vf2MPbinDF0ce802HniDJ`ANsPaEyuWr~7Y613A6p^JekO=Hkw@ZkqF(>B5^=egiT65##71)zs?yFRFyP3;+NC delta 199 zcmZo@VQlc2;K0bZ(eXGV%fJ8s|4-&&l8^;4xEUB2cz~D}i1~n+ABY8j_}|9B^^6k} z1SYZgFfvV6WRVvR5U4pg;rU5MW}vKtB#>ZWnB1spKY1TZ7Y7TF12pXaL6<}dx S+srB@%Q@N1@zmrAEFu7`f;yi7 diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/block_small.png b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/block_small.png new file mode 100644 index 0000000000000000000000000000000000000000..cea7cd0f773a6efa03c67223824bf0010bf88755 GIT binary patch literal 3662 zcmV-U4zclxP)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 literal 0 HcmV?d00001 diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/delete_small.png b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/delete_small.png new file mode 100644 index 0000000000000000000000000000000000000000..c3134399aeba892e0548b048a8fa3189af107e6d GIT binary patch literal 3270 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 Eg7k?gDgXcg literal 0 HcmV?d00001 diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/info_small.png b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/info_small.png new file mode 100644 index 0000000000000000000000000000000000000000..2794af30db5edb40fbbf9c2316d8f351c297dc3e GIT binary patch literal 3486 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 M07*qoM6N<$g0z~3*Z=?k literal 0 HcmV?d00001 diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/plus_small.png b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/plus_small.png new file mode 100644 index 0000000000000000000000000000000000000000..c78afd1d534b08a8c31303842f0609229a5a07a5 GIT binary patch literal 3174 zcmV-s44LzZP)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 literal 0 HcmV?d00001 diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/tick_small.png b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/tick_small.png new file mode 100644 index 0000000000000000000000000000000000000000..abc312f1862bcc968d71305f2e02c31344c1ec33 GIT binary patch literal 3141 zcmV-L47&4)P)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 literal 0 HcmV?d00001 diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/warning_small.png b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/warning_small.png new file mode 100644 index 0000000000000000000000000000000000000000..86668e4e07ad5d14ecf46e53812a5b96d45fc23e GIT binary patch literal 3235 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 VYu1#@6ea)w002ovPDHLkV1isZISv2- literal 0 HcmV?d00001 diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.addin b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.addin index 35d4e939c74..642c86ced5f 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.addin +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.addin @@ -14,6 +14,6 @@ + class = "ICSharpCode.ShortcutsManagement.Dialogs.ShortcutsManagementOptionsPanel" /> diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.csproj b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.csproj index 7428dac0ac9..44f9d76e0ac 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.csproj +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.csproj @@ -62,6 +62,8 @@ 3.5 + + 3.5 @@ -88,6 +90,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -142,11 +148,14 @@ Settings.settings True + - + + MultiKeyGestureTextBox.xaml + ShortcutManagementWindow.xaml @@ -157,6 +166,7 @@ ShortcutsTreeView.xaml + @@ -176,6 +186,13 @@ + + + + + + + Always diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/BoolToVisibilityConverter.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/BoolToVisibilityConverter.cs index f9e3f8719f9..b7bdf4df198 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/BoolToVisibilityConverter.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/BoolToVisibilityConverter.cs @@ -26,12 +26,12 @@ public object Convert(object value, Type targetType, object parameter, CultureIn return (bool)value ? "Visible" : hidden; } - throw new NotImplementedException(); + throw new NotSupportedException(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); + throw new NotSupportedException(); } } } diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/GesturesCollectionConverter.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/GesturesCollectionConverter.cs index dec24891388..a9439c878fa 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/GesturesCollectionConverter.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/GesturesCollectionConverter.cs @@ -31,7 +31,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn foreach (var gesture in (ObservableCollection)value) { inputGestureCollection.Add(gesture); } - return new InputGestureCollectionConverter().ConvertToInvariantString(inputGestureCollection).Replace("|", " | "); + return new InputGestureCollectionConverter().ConvertToInvariantString(inputGestureCollection); } return value.ToString(); diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/InputGestureConverter.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/InputGestureConverter.cs index 908e7c3a685..d8431a8f844 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/InputGestureConverter.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Converters/InputGestureConverter.cs @@ -2,6 +2,7 @@ using System.Globalization; using System.Windows.Data; using System.Windows.Input; +using ICSharpCode.Core.Presentation; namespace ICSharpCode.ShortcutsManagement.Converters { @@ -20,6 +21,11 @@ public class InputGestureConverter : IValueConverter /// public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { + if (value is MultiKeyGesture && targetType == typeof(string)) + { + return new MultiKeyGestureConverter().ConvertToInvariantString(value).Replace("+", " + "); + } + if(value is KeyGesture && targetType == typeof(string)) { return new KeyGestureConverter().ConvertToInvariantString(value).Replace("+", " + "); diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/AddIn.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/AddIn.cs index 92837eec28b..9a7f7010d0b 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/AddIn.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/AddIn.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel; namespace ICSharpCode.ShortcutsManagement.Data @@ -73,17 +72,6 @@ public AddIn(string addInName) Categories = new List(); } - /// - /// Invoke dependency property changed event - /// - /// Name of dependency property from this classs - private void InvokePropertyChanged(string propertyName) - { - if (PropertyChanged != null) { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } - } - /// /// Find shortcut by shortcutId in add-in categories /// @@ -115,6 +103,9 @@ public object Clone() return clonedAddIn; } + /// + /// Sort add-in sub categories + /// public void SortSubEntries() { Categories.Sort((a, b) => a.Name.CompareTo(b.Name)); @@ -129,12 +120,29 @@ public void SortSubEntries() /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// Compare add-in to other instances of + /// + /// Compared object + /// Comparison result public int CompareTo(object obj) { if (obj is ShortcutCategory) return 1; if (obj is Shortcut) return 1; var addInObj = (AddIn)obj; return Name.CompareTo(addInObj.Name); - } + } + + /// + /// Invoke dependency property changed event + /// + /// Name of dependency property from this classs + private void InvokePropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } } } diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/GestureFilterMode.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/GestureFilterMode.cs new file mode 100644 index 00000000000..e23ea03b8ef --- /dev/null +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/GestureFilterMode.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.ShortcutsManagement.Data +{ + /// + /// Gesture filtering mode + /// + public enum GestureFilterMode + { + /// + /// Match is successful if template gesture strictly matches compared gesture + /// + StrictlyMatches, + + /// + /// Match is successfull if template gesture partly matches compared geture. + /// Template is found in any place within matched gesture + /// + PartlyMatches, + + /// + /// match is successfull if matched gesture starts with provided template + /// + StartsWith + } +} diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/IShortcutTreeEntry.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/IShortcutTreeEntry.cs index 4c8b1e446a9..da6532d5006 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/IShortcutTreeEntry.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/IShortcutTreeEntry.cs @@ -1,24 +1,35 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ICSharpCode.ShortcutsManagement.Data { public interface IShortcutTreeEntry : IComparable, ICloneable { + /// + /// Shortcut entry name displayed in shortcuts tree + /// string Name { get; set; } + /// + /// Specifies whether shortcut tree entry is visible + /// bool IsVisible { get; set; } + /// + /// Sort shortcut entry sub elements + /// void SortSubEntries(); + /// + /// Search for shortcut in this shortcut entry and sub-elements + /// + /// + /// Shortcut FindShortcut(string shortcutId); } } diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/KeyGestureTemplate.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/KeyGestureTemplate.cs deleted file mode 100644 index 3aec34d4426..00000000000 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/KeyGestureTemplate.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Text; -using System.Windows.Input; - -namespace ICSharpCode.ShortcutsManagement.Data -{ - /// - /// Describes full key gesture or part of key gesture - /// - public class KeyGestureTemplate - { - /// - /// Gets the key associated with key gesture template - /// - public Key Key - { - get; - private set; - } - - /// - /// Get modifier keys associated with key gesture template - /// - public ModifierKeys Modifiers - { - get; - private set; - } - - /// - /// Create new instance of from - /// - /// Arguments generated by key event - public KeyGestureTemplate(KeyEventArgs keyEventArgs) - { - var keyboardDevice = (KeyboardDevice)keyEventArgs.Device; - - Key = keyEventArgs.Key; - Modifiers = keyboardDevice.Modifiers; - } - - /// - /// Create new instance of key gesture template from key gesture - /// - /// Key gesture - public KeyGestureTemplate(KeyGesture gesture) - { - Key = gesture.Key; - Modifiers = gesture.Modifiers; - } - - /// - /// Create new instance of key gesture template from key and modifiers - /// - /// The key associated with key gesture template - /// Modifier keys associated with key gesture template - public KeyGestureTemplate(Key key, ModifierKeys modifiers) - { - Key = key; - Modifiers = modifiers; - } - - /// - /// Create key gesture template from key only (without modifiers) - /// - /// The key associated with key gesture template - public KeyGestureTemplate(Key key) - { - Key = key; - Modifiers = ModifierKeys.None; - } - - /// - /// Determines whether key gesture matches this key gesture template - /// - /// Key gesture - /// If true both modifiers and key should match. Otherwice gesture matches to template if template describe only part of shortcut - /// - public bool Matches(KeyGesture gesture, bool strictMatch) - { - if(strictMatch) { - return Key == gesture.Key && Modifiers == gesture.Modifiers; - } - - var keyMatches = Key == gesture.Key; - - // 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 = gesture.Modifiers - (gesture.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}, Key) >= 0) { - return modifierMatches; - } - - return modifierMatches && keyMatches; - } - - public bool MatchesCollection(InputGestureCollection gestures, bool strictMatch) - { - foreach (InputGesture gesture in gestures) - { - if(gesture is KeyGesture && Matches((KeyGesture)gesture, strictMatch)) - { - return true; - } - } - - return false; - } - - /// - /// Returns string that represents - /// - /// String - public override string ToString() - { - var pressedButton = new StringBuilder(); - - // Display modifier - if ((Modifiers & ModifierKeys.Control) > 0) - { - pressedButton.Append("Ctrl + "); - } - if ((Modifiers & ModifierKeys.Windows) > 0) - { - pressedButton.Append("Windows + "); - } - if ((Modifiers & ModifierKeys.Alt) > 0) - { - pressedButton.Append("Alt + "); - } - if ((Modifiers & ModifierKeys.Shift) > 0) - { - pressedButton.Append("Shift + "); - } - - // Filter modifier keys from being displayed twice (example: Control + 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(); - } - } -} diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/Shortcut.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/Shortcut.cs index fea01099784..6be150bf0b1 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/Shortcut.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/Shortcut.cs @@ -79,6 +79,11 @@ public bool IsVisible } } + /// + /// Notify observers about property changes + /// + public event PropertyChangedEventHandler PropertyChanged; + /// /// Create new instance of shortcut /// @@ -143,23 +148,10 @@ public object Clone() } /// - /// Invoke dependency property changed event - /// - /// Name of dependency property from this classs - private void InvokePropertyChanged(string propertyName) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } - } - - /// - /// Notify observers about property changes + /// Compare shortcut to other instances of /// - public event PropertyChangedEventHandler PropertyChanged; - - + /// Compared object + /// Comparison result public int CompareTo(object obj) { if (obj is AddIn) return -1; @@ -169,8 +161,25 @@ public int CompareTo(object obj) return Name.CompareTo(shortcutObj.Name); } + /// + /// Returns this instance if searched id matches + /// + /// Searched shortcut id + /// Found shortcut instance or null public Shortcut FindShortcut(string shortcutId) { return Id == shortcutId ? this : null; } + + /// + /// Invoke dependency property changed event + /// + /// Name of dependency property from this classs + private void InvokePropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } } } diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutCategory.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutCategory.cs index 3d1cf2f5093..371536cd6bf 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutCategory.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutCategory.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel; namespace ICSharpCode.ShortcutsManagement.Data @@ -72,6 +71,11 @@ public List Shortcuts private set; } + /// + /// Notify observers about property changes + /// + public event PropertyChangedEventHandler PropertyChanged; + /// /// Create new instance of category /// @@ -103,6 +107,9 @@ public object Clone() return clonedCategory; } + /// + /// Sort category shortcuts + /// public void SortSubEntries() { SubCategories.Sort((a, b) => a.Name.CompareTo(b.Name)); @@ -140,21 +147,10 @@ public Shortcut FindShortcut(string shortcutId) } /// - /// Invoke dependency property changed event + /// Compare shortcut category to other instances of /// - /// Name of dependency property from this classs - private void InvokePropertyChanged(string propertyName) - { - if (PropertyChanged != null) { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } - } - - /// - /// Notify observers about property changes - /// - public event PropertyChangedEventHandler PropertyChanged; - + /// Compared object + /// Comparison result public int CompareTo(object obj) { if (obj is AddIn) return -1; @@ -163,5 +159,17 @@ public int CompareTo(object obj) var categoryObj = (ShortcutCategory)obj; return Name.CompareTo(categoryObj.Name); } + + /// + /// Invoke dependency property changed event + /// + /// Name of dependency property from this classs + private void InvokePropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } } } diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs index 28574e9ad9a..eedca764833 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Windows.Input; +using ICSharpCode.Core.Presentation; +using ICSharpCode.ShortcutsManagement.Extensions; namespace ICSharpCode.ShortcutsManagement.Data { @@ -94,31 +97,32 @@ private static bool HideShortcut(ShortcutCategory category, Shortcut filteredSho /// /// Hides add-ins and sub-categories if there are no sub-elements left /// - /// Gesture template (Uncompleted gesture) - /// If false filter gestures which with only partial match - public void FilterGesture(KeyGestureTemplate keyGestureTemplate, bool strictMatch) + /// Gesture template which should match shortcut gesture partly to make it visible + /// Filtering mode + public void FilterGesture(InputGesture inputGestureTemplate, GestureFilterMode mode) { - FilterGesture(new List { keyGestureTemplate }, strictMatch); + FilterGesture(new InputGestureCollection(new[] { inputGestureTemplate }), mode); } /// - /// Filter gestures matching provided key gesture template + /// Filter gestures matching one of provided gesture templates /// /// Hides add-ins and sub-categories if there are no sub-elements left /// - /// Gesture templates collection (Uncompleted gestures) - /// If false filter gestures which with only partial match - public void FilterGesture(ICollection keyGestureTemplateCollection, bool strictMatch) + /// Collection of gesture templates which (atleast one) should match shortcut gesture partly to make it visible + /// Filtering mode + public void FilterGesture(InputGestureCollection inputGestureTemplateCollection, GestureFilterMode mode) { + Debug.WriteLine("Changed to" + new InputGestureCollectionConverter().ConvertToInvariantString(inputGestureTemplateCollection)); foreach (var entry in RootEntries) { var subCategoryIsVisible = false; + // Filter root addin and sub-elements var rootAddIn = entry as AddIn; - if (rootAddIn != null) - { + if (rootAddIn != null) { foreach (var category in rootAddIn.Categories) { - if (FilterGesture(category, keyGestureTemplateCollection, strictMatch)) { + if (FilterGesture(category, inputGestureTemplateCollection, mode)) { subCategoryIsVisible = true; } } @@ -127,16 +131,18 @@ public void FilterGesture(ICollection keyGestureTemplateColl rootAddIn.IsVisible = subCategoryIsVisible; } + // Filter root category and sub-elements var rootCategory = entry as ShortcutCategory; if (rootCategory != null) { - FilterGesture(rootCategory, keyGestureTemplateCollection, strictMatch); + FilterGesture(rootCategory, inputGestureTemplateCollection, mode); } + // Filter root shortcut var rootShortcut = entry as Shortcut; if (rootShortcut != null) { rootShortcut.IsVisible = false; - foreach (var template in keyGestureTemplateCollection) { - if (template.MatchesCollection(new InputGestureCollection(rootShortcut.Gestures), strictMatch)) { + foreach (InputGesture template in inputGestureTemplateCollection) { + if (template.MatchesCollection(new InputGestureCollection(rootShortcut.Gestures), mode)) { rootShortcut.IsVisible = true; break; } @@ -146,17 +152,19 @@ public void FilterGesture(ICollection keyGestureTemplateColl } /// - /// Filter gestures matching one of provided key gesture templates from templates collection + /// Filter gestures matching one of provided gesture templates from templates collection /// /// Category to filter - /// Gesture templates collection (Uncompleted gestures) + /// Collection of gesture templates which (atleast one) should match shortcut gesture partly to make it visible + /// Filtering mode /// - private static bool FilterGesture(ShortcutCategory category, IEnumerable keyGestureTemplateCollection, bool strictMatch) + private static bool FilterGesture(ShortcutCategory category, InputGestureCollection inputGestureTemplateCollection, GestureFilterMode mode) { // Apply filter to sub-categories var isSubElementVisible = false; foreach (var subCategory in category.SubCategories) { - if (FilterGesture(subCategory, keyGestureTemplateCollection, strictMatch)) { + if (FilterGesture(subCategory, inputGestureTemplateCollection, mode)) + { isSubElementVisible = true; } } @@ -164,8 +172,15 @@ private static bool FilterGesture(ShortcutCategory category, IEnumerable 0 && ((KeyGesture)shortcut.Gestures[0]).Key == Key.F5) + { + + } + + if (template.MatchesCollection(new InputGestureCollection(shortcut.Gestures), mode)) + { gestureMatched = true; break; } @@ -221,7 +236,7 @@ public void Filter(string filterString) var rootShortcut = entry as Shortcut; if (rootShortcut != null) { - rootShortcut.IsVisible = rootShortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0; + rootShortcut.IsVisible = filterString == null || rootShortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0; } } } @@ -252,7 +267,8 @@ private static bool Filter(ShortcutCategory category, string filterString, bool? // Filter shortcuts which text match the filter foreach (var shortcut in category.Shortcuts) { - if ((forseMatch.HasValue && forseMatch.Value) || shortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0) { + if ((forseMatch.HasValue && forseMatch.Value) || filterString == null || shortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0) + { shortcut.IsVisible = true; isSubElementVisible = true; } diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml new file mode 100644 index 00000000000..869f1a22b18 --- /dev/null +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml.cs b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml.cs new file mode 100644 index 00000000000..fa20bc82bc6 --- /dev/null +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/MultiKeyGestureTextBox.xaml.cs @@ -0,0 +1,305 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using ICSharpCode.Core; +using ICSharpCode.Core.Presentation; + +namespace ICSharpCode.ShortcutsManagement.Dialogs +{ + /// + /// Notification type enumeration + /// + public enum NotificationType + { + /// + /// A valid gesture is entered so far + /// + Valid, + + /// + /// Gesture is being entered, but is not valid yet + /// + Invalid, + + /// + /// Gesture was successfully added to gestures collection + /// + Added, + + /// + /// Failed to add gesture to gestures collection + /// + Failed, + + /// + /// Notification message is not displayed + /// + None + } + + /// + /// Represents a textbox suited for entering key gestures + /// + public partial class MultiKeyGestureTextBox : UserControl + { + /// + /// Identifies dependency property + /// + public static readonly DependencyProperty TextBoxBorderThicknessProperty = DependencyProperty.Register( + "TextBoxBorderThickness", + typeof(int), + typeof(MultiKeyGestureTextBox), + new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsRender)); + + /// + /// Specifies text box border thickness + /// + public int TextBoxBorderThickness + { + get { + return (int)GetValue(TextBoxBorderThicknessProperty); + } + set { + SetValue(TextBoxBorderThicknessProperty, value); + } + } + + /// + /// Key gesture entered in text box + /// + public KeyGesture Gesture + { + get { + if (enteredKeyGestureSequence == null || enteredKeyGestureSequence.Count == 0) { + return null; + } + + if (enteredKeyGestureSequence.Count == 1) { + return enteredKeyGestureSequence.First(); + } + + return new MultiKeyGesture(enteredKeyGestureSequence); + } + } + + /// + /// Event which is raised when gesture entered in text box changes + /// + public event EventHandler GestureChanged; + + /// + /// Identifies dependency property + /// + public static readonly DependencyProperty NotificationVisibilityProperty = DependencyProperty.Register( + "NotificationVisibility", + typeof(Visibility), + typeof(MultiKeyGestureTextBox), + new FrameworkPropertyMetadata(Visibility.Visible, FrameworkPropertyMetadataOptions.AffectsRender)); + + /// + /// Whether notifications are displayed under textbox control + /// + public Visibility NotificationVisibility + { + get { + return (Visibility)GetValue(NotificationVisibilityProperty); + } + set { + SetValue(NotificationVisibilityProperty, value); + } + } + + /// + /// Identifies dependency property + /// + public static readonly DependencyProperty NotificationTypeProperty = DependencyProperty.Register( + "NotificationType", + typeof(NotificationType), + typeof(MultiKeyGestureTextBox), + new FrameworkPropertyMetadata(NotificationType.None, FrameworkPropertyMetadataOptions.AffectsRender)); + + /// + /// Specifies displayed notification type + /// + public NotificationType NotificationType + { + get { + return (NotificationType)GetValue(NotificationTypeProperty); + } + set { + SetValue(NotificationTypeProperty, value); + } + } + + /// + /// Identifies dependency property + /// + public static readonly DependencyProperty NotificationTextProperty = DependencyProperty.Register( + "NotificationText", + typeof(string), + typeof(MultiKeyGestureTextBox), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); + + /// + /// Specifies displayed notification text + /// + public string NotificationText + { + get { + return (string)GetValue(NotificationTextProperty); + } + set { + SetValue(NotificationTextProperty, value); + } + } + + /// + /// Last entered chords + /// + private readonly List enteredKeyGestureSequence = new List(); + + /// + /// Time when last successfull chord was entered + /// + private DateTime lastEnterTime = DateTime.Now; + + /// + /// Creates instance of + /// + public MultiKeyGestureTextBox() + { + InitializeComponent(); + } + + /// + /// Displays notifications under gesture text box + /// + /// Notification text + /// Notification type + public void DisplayNotification(string notificationText, NotificationType type) + { + NotificationText = notificationText; + NotificationType = type; + } + + /// + /// Clears all text area, chords and hides notification + /// + public void Clear() + { + enteredKeyGestureSequence.Clear(); + shortcutTextBox.Text = ""; + DisplayNotification("", NotificationType.None); + } + + /// + /// Raised when clicked on "Clear" button to the right from gesture text box + /// + /// + /// + private void clearTextBox_Click(object sender, RoutedEventArgs e) + { + Clear(); + } + + + /// + /// Raised when text inside textbox changes + /// + /// Sender object + /// Event arguments + void shortcutTextBox_TextChanged(object sender, TextChangedEventArgs e) + { + if (GestureChanged != null) { + GestureChanged.Invoke(sender, new EventArgs()); + } + } + + /// + /// Raised before user presses any key inside text box + /// + /// Sender object + /// Event argument + private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) + { + e.Handled = true; + + // If a key is holded for a longer time key event is raised repeatedly. + // We don't want to handle this kind of events + if (e.IsRepeat) { + return; + } + + // If delete or backspace button is pressed + if (e.Key == Key.Back || e.Key == Key.Delete) { + Clear(); + return; + } + + // Check whether time given for chord entry haven't expired yet + if (DateTime.Now - lastEnterTime > MultiKeyGesture.DelayBetweenGestureInputs) { + if (enteredKeyGestureSequence.Count > 0) { + DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.TimeExpired}"), NotificationType.Invalid); + } + + Clear(); + lastEnterTime = DateTime.Now; + } + + var partialKeyGesture = new PartialKeyGesture(e); + + var lastGesture = enteredKeyGestureSequence.Count > 0 ? enteredKeyGestureSequence.LastOrDefault() : null; + var isLastGestureComplete = lastGesture != null && lastGesture.Key != Key.None; + var isContinuedGesture = lastGesture != null && partialKeyGesture.Modifiers - (partialKeyGesture.Modifiers ^ lastGesture.Modifiers) >= 0; + + // If continuing previous chord + if (!isLastGestureComplete && isContinuedGesture) + { + enteredKeyGestureSequence.RemoveAt(enteredKeyGestureSequence.Count - 1); + } + // If previous chord is unfinished and second chor is already entered + // start from scratch. + else if (!isLastGestureComplete) + { + DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.SequenceIsNotCoherent}"), NotificationType.Invalid); + Clear(); + } + + // If successfully finished another chord give more time + if (partialKeyGesture.Key != Key.None) + { + lastEnterTime = DateTime.Now; + } + + enteredKeyGestureSequence.Add(partialKeyGesture); + + // Create a multi key gesture if entered more than one chord + if (enteredKeyGestureSequence.Count > 0) + { + var multiKeyGesture = new MultiKeyGesture(enteredKeyGestureSequence); + var multiKeyGestureString = new MultiKeyGestureConverter().ConvertToInvariantString(multiKeyGesture); + shortcutTextBox.Text = multiKeyGestureString; + } + else + { + Clear(); + } + + if (enteredKeyGestureSequence[0].Modifiers == ModifierKeys.None) + { + DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.FirstChordIsIncomplete}"), NotificationType.Invalid); + } + else if (partialKeyGesture.Key == Key.None) + { + DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.LastChordIsIncomplete}"), NotificationType.Invalid); + } + else + { + DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.GestureIsValid}"), NotificationType.Valid); + } + } + } +} diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml index 0d837dda4b7..a34afe9c19a 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml @@ -8,8 +8,7 @@ - - + @@ -21,7 +20,7 @@ - + diff --git a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutManagementWindow.xaml b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutManagementWindow.xaml index 507d2672602..501e44c9268 100644 --- a/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutManagementWindow.xaml +++ b/src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutManagementWindow.xaml @@ -1,14 +1,21 @@ - + xmlns:Dialogs="clr-namespace:ICSharpCode.ShortcutsManagement.Dialogs" + Title="{Binding Text}" + MinHeight="400" + MinWidth="400" + x:Name="_this"> + + + @@ -19,27 +26,27 @@ - + -