Browse Source

InputBindingCategory class, nested categories

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/shortcuts@4285 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts^2
Sergej Andrejev 16 years ago
parent
commit
cf7680a3ee
  1. 16
      AddIns/ICSharpCode.SharpDevelop.addin
  2. BIN
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement.suo
  3. 8
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/StringResources.resx
  4. 3
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs
  5. 1
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml
  6. 185
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsManagementOptionsPanel.xaml.cs
  7. 71
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Window1.xaml.cs
  8. 4
      src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
  9. 79
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs
  10. 4
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs
  11. 47
      src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingCategory.cs
  12. 6
      src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs
  13. 1
      src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
  14. 2
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs

16
AddIns/ICSharpCode.SharpDevelop.addin

@ -51,6 +51,22 @@
<Import assembly=":ICSharpCode.TextEditor"/> <Import assembly=":ICSharpCode.TextEditor"/>
</Runtime> </Runtime>
<Path name="/SharpDevelop/Categories">
<Category id="Debug" text="Debug" />
<Categoru id="MainMenu" text="Main menu">
<Category id="File" text="File" />
<Category id="Edit" text="Edit" />
<Category id="Project" text="Project" />
<Category id="Build" text="Build" />
<Category id="Debug" text="Debug" />
<Category id="Search" text="Search" />
<Category id="QualityTools" text="Quality Tools" />
<Category id="XML" text="XML" />
<Category id="Tools" text="Tools" />
<Category id="Window" text="Window" />
</Categoru>
</Path>
<Path name="/SharpDevelop/Workbench/RoutedUICommands"> <Path name="/SharpDevelop/Workbench/RoutedUICommands">
<RoutedUICommand name="SDTestCommands.Test" text="Create new file" /> <RoutedUICommand name="SDTestCommands.Test" text="Create new file" />

BIN
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement.suo

Binary file not shown.

8
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Resources/StringResources.resx

@ -128,8 +128,16 @@
</data> </data>
<data name="Global.CancelButtonText" xml:space="preserve"> <data name="Global.CancelButtonText" xml:space="preserve">
<value>_Cancel</value> <value>_Cancel</value>
<comment>For testing outside SD</comment>
</data> </data>
<data name="Global.OKButtonText" xml:space="preserve"> <data name="Global.OKButtonText" xml:space="preserve">
<value>_OK</value> <value>_OK</value>
<comment>For testing outside SD</comment>
</data>
<data name="ShortcutsManagement.UnspecifiedAddInName" xml:space="preserve">
<value>Unspecified</value>
</data>
<data name="ShortcutsManagement.UnspecifiedCategoryName" xml:space="preserve">
<value>Uncategorized</value>
</data> </data>
</root> </root>

3
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs

@ -261,7 +261,8 @@ namespace ICSharpCode.ShortcutsManagement.Data
} }
} }
return category.IsVisible = (forseMatch.HasValue && forseMatch.Value) || isSubElementVisible; // Show category if has sub elements, forced or matches search filter
return category.IsVisible = (forseMatch.HasValue && forseMatch.Value && (category.SubCategories.Count > 0 || category.Shortcuts.Count > 0)) || isSubElementVisible;
} }
} }
} }

1
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml

@ -128,6 +128,7 @@
<DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="AddIn"> <DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="AddIn">
<Setter TargetName="InnerBorder" Property="Panel.Background" Value="#AEFFA8" /> <Setter TargetName="InnerBorder" Property="Panel.Background" Value="#AEFFA8" />
<Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#000000" /> <Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#000000" />
<Setter TargetName="OuterBorder" Property="Margin" Value="0" />
</DataTrigger> </DataTrigger>
<DataTrigger Binding="{Binding Path=IsVisible}" Value="false"> <DataTrigger Binding="{Binding Path=IsVisible}" Value="false">
<Setter Property="Visibility" Value="Collapsed" /> <Setter Property="Visibility" Value="Collapsed" />

185
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsManagementOptionsPanel.xaml.cs

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
@ -17,131 +16,128 @@ namespace ICSharpCode.ShortcutsManagement
/// </summary> /// </summary>
public partial class ShortcutsManagementOptionsPanel : UserControl, IOptionPanel public partial class ShortcutsManagementOptionsPanel : UserControl, IOptionPanel
{ {
/// <summary>
/// Stores shortcut entry to input binding convertion map
/// </summary>
private readonly Dictionary<Shortcut, InputBindingInfo> shortcutsMap = new Dictionary<Shortcut, InputBindingInfo>(); private readonly Dictionary<Shortcut, InputBindingInfo> shortcutsMap = new Dictionary<Shortcut, InputBindingInfo>();
private static InputGestureCollection GetGestures(string gesturesString)
{
var converter = new InputGestureCollectionConverter();
return (InputGestureCollection)converter.ConvertFromInvariantString(gesturesString);
}
public ShortcutsManagementOptionsPanel() public ShortcutsManagementOptionsPanel()
{ {
ResourceService.RegisterStrings("ICSharpCode.ShortcutsManagement.Resources.StringResources", GetType().Assembly); ResourceService.RegisterStrings("ICSharpCode.ShortcutsManagement.Resources.StringResources", GetType().Assembly);
InitializeComponent(); InitializeComponent();
// Test data
var rootEntries = new ObservableCollection<IShortcutTreeEntry>();
var addin1 = new ShortcutManagement.AddIn("SharpDevelop");
rootEntries.Add(addin1);
addin1.Categories.Add(new ShortcutCategory("Editing"));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Copy", GetGestures("Ctrl + C")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Paste", GetGestures("Ctrl + V | Ctrl+Insert")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Cut", GetGestures("Ctrl + X")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Undo", GetGestures("Ctrl + Z")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Redo", GetGestures("Ctrl + Y")));
addin1.Categories.Add(new ShortcutCategory("Building"));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Build", GetGestures("Ctrl + Shift+B")));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Run", GetGestures("F5")));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Run without debuger", GetGestures("Ctrl + F5")));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8")));
addin1.Categories.Add(new ShortcutCategory("Uncategorized"));
addin1.Categories[2].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8")));
var addin2 = new ShortcutManagement.AddIn("Search & replace");
rootEntries.Add(addin2);
addin2.Categories.Add(new ShortcutCategory("Uncategorized"));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Quick find", GetGestures("Ctrl + F")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Quick replace", GetGestures("Ctrl + H")));
addin2.Categories[0].SubCategories.Add(new ShortcutCategory("Subcategory 3"));
addin2.Categories[0].SubCategories[0].SubCategories.Add(new ShortcutCategory("Subcategory 4"));
addin2.Categories[0].SubCategories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut N", GetGestures("Ctrl + N")));
addin2.Categories[0].SubCategories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut O", GetGestures("Ctrl + O")));
addin2.Categories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut L", GetGestures("Ctrl + L")));
addin2.Categories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut M", GetGestures("Ctrl + M")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Find in files", GetGestures("Ctrl + Shift + F | Ctrl + Shift + H | Ctrl + I")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Replace in files", GetGestures("Ctrl + Shift + H")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Find symbol", null));
var addin3 = new ShortcutManagement.AddIn("Unspecified");
rootEntries.Add(addin3);
addin3.Categories.Add(new ShortcutCategory("Uncategorized"));
addin3.Categories[0].Shortcuts.Add(new Shortcut("Test regex expression", null));
var rootCategory = new ShortcutCategory("Without addin");
rootEntries.Add(rootCategory);
rootCategory.SubCategories.Add(new ShortcutCategory("Subcategory 1"));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut H", GetGestures("Ctrl + H")));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut I", GetGestures("Ctrl + I")));
rootCategory.SubCategories.Add(new ShortcutCategory("Subcategory 2"));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut J", GetGestures("Ctrl + J")));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut K", GetGestures("Ctrl + K")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut A", GetGestures("Ctrl + A")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut B", GetGestures("Ctrl + B")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut C", GetGestures("Ctrl + C")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut D", GetGestures("Ctrl + D")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut E", null));
rootEntries.Add(new Shortcut("Shortcut F", GetGestures("Ctrl + F")));
rootEntries.Add(new Shortcut("Shortcut G", GetGestures("Ctrl + G")));
shortcutsManagementOptionsPanel.DataContext = rootEntries;
} }
public void LoadOptions() public void LoadOptions()
{ {
// Load shortcuts for real // Root shortcut tree entries
var unspecifiedAddInSection = new ShortcutManagement.AddIn("Unspecified"); var rootEntries = new List<IShortcutTreeEntry>();
unspecifiedAddInSection.Categories.Add(new ShortcutCategory("Uncategorized"));
var rootEntries = new List<IShortcutTreeEntry>();
rootEntries.Add(unspecifiedAddInSection);
// Stores SD add-in to add-in section convertion map
var addInsMap = new Dictionary<AddIn, ShortcutManagement.AddIn>(); var addInsMap = new Dictionary<AddIn, ShortcutManagement.AddIn>();
var categoriesMap = new Dictionary<ShortcutManagement.AddIn, Dictionary<string, ShortcutCategory>>();
// Stores SD input binding category to category section convertion map
var categoriesMap = new Dictionary<ShortcutManagement.AddIn, Dictionary<InputBindingCategory, ShortcutCategory>>();
// Create default add-in for input bindings which don't specify add-in
var unspecifiedAddInSection = new ShortcutManagement.AddIn(StringParser.Parse("${res:ShortcutsManagement.UnspecifiedAddInName}"));
unspecifiedAddInSection.Categories.Add(new ShortcutCategory(StringParser.Parse("${res:ShortcutsManagement.UnspecifiedCategoryName}")));
rootEntries.Add(unspecifiedAddInSection);
// Go through all input bindings
var inputBindingInfos = CommandsRegistry.FindInputBindingInfos(null, null, null); var inputBindingInfos = CommandsRegistry.FindInputBindingInfos(null, null, null);
foreach(var inputBindingInfo in inputBindingInfos) { foreach(var inputBindingInfo in inputBindingInfos) {
// Find appropriate or create new add-in section for input binding
ShortcutManagement.AddIn addinSection; ShortcutManagement.AddIn addinSection;
if(inputBindingInfo.AddIn == null) { if (inputBindingInfo.AddIn == null) {
addinSection = unspecifiedAddInSection; addinSection = unspecifiedAddInSection;
} else if (addInsMap.ContainsKey(inputBindingInfo.AddIn)) { } else if (addInsMap.ContainsKey(inputBindingInfo.AddIn)) {
addinSection = addInsMap[inputBindingInfo.AddIn]; addinSection = addInsMap[inputBindingInfo.AddIn];
} else { } else {
addinSection = new ShortcutManagement.AddIn(inputBindingInfo.AddIn.Name); addinSection = new ShortcutManagement.AddIn(inputBindingInfo.AddIn.Name);
addinSection.Categories.Add(new ShortcutCategory("Uncategorized")); addinSection.Categories.Add(new ShortcutCategory(StringParser.Parse("${res:ShortcutsManagement.UnspecifiedCategoryName}")));
addInsMap.Add(inputBindingInfo.AddIn, addinSection); addInsMap.Add(inputBindingInfo.AddIn, addinSection);
categoriesMap.Add(addinSection, new Dictionary<string, ShortcutCategory>()); categoriesMap.Add(addinSection, new Dictionary<InputBindingCategory, ShortcutCategory>());
rootEntries.Add(addinSection); rootEntries.Add(addinSection);
} }
ShortcutCategory categorySection; // Find appropriate or create new category sections within add-in section for input binding
if(string.IsNullOrEmpty(inputBindingInfo.CategoryName)) { var shortcutCategorySections = new List<ShortcutCategory>();
categorySection = addinSection.Categories[0]; if (inputBindingInfo.Categories.Count == 0) {
} else if(!categoriesMap[addinSection].ContainsKey(inputBindingInfo.CategoryName)) { // If no category specified assign to "Uncotegorized" category
categorySection = new ShortcutCategory(inputBindingInfo.CategoryName); shortcutCategorySections.Add(addinSection.Categories[0]);
addinSection.Categories.Add(categorySection);
categoriesMap[addinSection].Add(inputBindingInfo.CategoryName, categorySection);
} else { } else {
categorySection = categoriesMap[addinSection][inputBindingInfo.CategoryName]; // Go throu all categories and find or create appropriate category sections
foreach (var bindingCategory in inputBindingInfo.Categories) {
ShortcutCategory categorySection;
if (categoriesMap[addinSection].ContainsKey(bindingCategory)) {
// If found appropriate category assign shortcut to it
categorySection = categoriesMap[addinSection][bindingCategory];
} else {
// Create appropriate category section and root category sections
// Create direct category to which shortcut will be assigned
var categoryName = StringParser.Parse(bindingCategory.Name);
categorySection = new ShortcutCategory(categoryName);
categoriesMap[addinSection].Add(bindingCategory, categorySection);
// Go down to root level and create all parent categories
var currentBindingCategory = bindingCategory;
var currentShortcutCategory = categorySection;
while (currentBindingCategory.ParentCategory != null) {
ShortcutCategory parentCategorySection;
if (!categoriesMap[addinSection].ContainsKey(currentBindingCategory.ParentCategory)) {
// Create parent category section if it's not created yet
var parentCategoryName = StringParser.Parse(currentBindingCategory.ParentCategory.Name);
parentCategorySection = new ShortcutCategory(parentCategoryName);
categoriesMap[addinSection].Add(currentBindingCategory.ParentCategory, parentCategorySection);
} else {
// Use existing category section as parent category section
parentCategorySection = categoriesMap[addinSection][currentBindingCategory.ParentCategory];
}
// Add current category section to root category section children
if (!parentCategorySection.SubCategories.Contains(currentShortcutCategory)) {
parentCategorySection.SubCategories.Add(currentShortcutCategory);
}
currentShortcutCategory = parentCategorySection;
currentBindingCategory = currentBindingCategory.ParentCategory;
}
// Add root category section to add-in categories list
if (!addinSection.Categories.Contains(currentShortcutCategory)) {
addinSection.Categories.Add(currentShortcutCategory);
}
}
shortcutCategorySections.Add(categorySection);
}
}
// Get shortcut entry text. Normaly shortcut entry text is equalt to routed command text
// but this value can be overriden through InputBindingInfo.RoutedCommandText value
var shortcutText = inputBindingInfo.RoutedCommand.Text;
if (!string.IsNullOrEmpty(inputBindingInfo.RoutedCommandText)) {
shortcutText = inputBindingInfo.RoutedCommandText;
} }
var shortcutText = !string.IsNullOrEmpty(inputBindingInfo.RoutedCommandText)
? inputBindingInfo.RoutedCommandText
: inputBindingInfo.RoutedCommand.Text;
shortcutText = StringParser.Parse(shortcutText); shortcutText = StringParser.Parse(shortcutText);
// Some commands have "&" sign to mark alternative key used to call this command from menu // Some commands have "&" sign to mark alternative key used to call this command from menu
// Strip this sign // Strip this sign from shortcut entry text
shortcutText = Regex.Replace(shortcutText, @"&([^\s])", @"$1"); shortcutText = Regex.Replace(shortcutText, @"&([^\s])", @"$1");
var shortcut = new Shortcut(shortcutText, inputBindingInfo.Gestures); var shortcut = new Shortcut(shortcutText, inputBindingInfo.Gestures);
categorySection.Shortcuts.Add(shortcut);
// Assign shortcut to all categories it is registered in
foreach (var categorySection in shortcutCategorySections) {
categorySection.Shortcuts.Add(shortcut);
}
shortcutsMap.Add(shortcut, inputBindingInfo); shortcutsMap.Add(shortcut, inputBindingInfo);
} }
rootEntries.Sort(); rootEntries.Sort();
@ -154,10 +150,9 @@ namespace ICSharpCode.ShortcutsManagement
shortcutsManagementOptionsPanel.DataContext = rootEntries; shortcutsManagementOptionsPanel.DataContext = rootEntries;
} }
public bool SaveOptions() { public bool SaveOptions()
{
foreach (var pair in shortcutsMap) foreach (var pair in shortcutsMap) {
{
var shortcut = pair.Key; var shortcut = pair.Key;
var inputBindingInfo = pair.Value; var inputBindingInfo = pair.Value;

71
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Window1.xaml.cs

@ -1,4 +1,9 @@
using System.Windows; using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using ICSharpCode.Core.Presentation;
using ICSharpCode.ShortcutsManagement.Data;
using AddInSection = ICSharpCode.ShortcutsManagement.Data.AddIn;
namespace ICSharpCode.ShortcutsManagement namespace ICSharpCode.ShortcutsManagement
{ {
@ -10,6 +15,70 @@ namespace ICSharpCode.ShortcutsManagement
public Window1() public Window1()
{ {
InitializeComponent(); InitializeComponent();
// Test data
var rootEntries = new ObservableCollection<IShortcutTreeEntry>();
var addin1 = new AddInSection("SharpDevelop");
rootEntries.Add(addin1);
addin1.Categories.Add(new ShortcutCategory("Editing"));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Copy", GetGestures("Ctrl + C")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Paste", GetGestures("Ctrl + V | Ctrl+Insert")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Cut", GetGestures("Ctrl + X")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Undo", GetGestures("Ctrl + Z")));
addin1.Categories[0].Shortcuts.Add(new Shortcut("Redo", GetGestures("Ctrl + Y")));
addin1.Categories.Add(new ShortcutCategory("Building"));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Build", GetGestures("Ctrl + Shift+B")));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Run", GetGestures("F5")));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Run without debuger", GetGestures("Ctrl + F5")));
addin1.Categories[1].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8")));
addin1.Categories.Add(new ShortcutCategory("Uncategorized"));
addin1.Categories[2].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8")));
var addin2 = new AddInSection("Search & replace");
rootEntries.Add(addin2);
addin2.Categories.Add(new ShortcutCategory("Uncategorized"));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Quick find", GetGestures("Ctrl + F")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Quick replace", GetGestures("Ctrl + H")));
addin2.Categories[0].SubCategories.Add(new ShortcutCategory("Subcategory 3"));
addin2.Categories[0].SubCategories[0].SubCategories.Add(new ShortcutCategory("Subcategory 4"));
addin2.Categories[0].SubCategories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut N", GetGestures("Ctrl + N")));
addin2.Categories[0].SubCategories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut O", GetGestures("Ctrl + O")));
addin2.Categories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut L", GetGestures("Ctrl + L")));
addin2.Categories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut M", GetGestures("Ctrl + M")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Find in files", GetGestures("Ctrl + Shift + F | Ctrl + Shift + H | Ctrl + I")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Replace in files", GetGestures("Ctrl + Shift + H")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Find symbol", null));
var addin3 = new AddInSection("Unspecified");
rootEntries.Add(addin3);
addin3.Categories.Add(new ShortcutCategory("Uncategorized"));
addin3.Categories[0].Shortcuts.Add(new Shortcut("Test regex expression", null));
var rootCategory = new ShortcutCategory("Without addin");
rootEntries.Add(rootCategory);
rootCategory.SubCategories.Add(new ShortcutCategory("Subcategory 1"));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut H", GetGestures("Ctrl + H")));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut I", GetGestures("Ctrl + I")));
rootCategory.SubCategories.Add(new ShortcutCategory("Subcategory 2"));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut J", GetGestures("Ctrl + J")));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut K", GetGestures("Ctrl + K")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut A", GetGestures("Ctrl + A")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut B", GetGestures("Ctrl + B")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut C", GetGestures("Ctrl + C")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut D", GetGestures("Ctrl + D")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut E", null));
rootEntries.Add(new Shortcut("Shortcut F", GetGestures("Ctrl + F")));
rootEntries.Add(new Shortcut("Shortcut G", GetGestures("Ctrl + G")));
optionsPanel.DataContext = rootEntries;
}
private static InputGestureCollection GetGestures(string gesturesString)
{
var converter = new InputGestureCollectionConverter();
return (InputGestureCollection)converter.ConvertFromInvariantString(gesturesString);
} }
} }
} }

4
src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs

@ -471,7 +471,7 @@ namespace ICSharpCode.SharpDevelop.Commands
} }
var routedCommandName = "SDViewCommands.ShowView_" + padContent.Class; var routedCommandName = "SDViewCommands.ShowView_" + padContent.Class;
var routedCommandText = "Show view \"" + MenuService.ConvertLabel(StringParser.Parse(padContent.Title)) + "\""; var routedCommandText = MenuService.ConvertLabel(StringParser.Parse(padContent.Title));
// TODO: fix this hack // TODO: fix this hack
if(!bindingsAssigned.Contains(routedCommandName)) { if(!bindingsAssigned.Contains(routedCommandName)) {
@ -497,7 +497,7 @@ namespace ICSharpCode.SharpDevelop.Commands
inputBindingInfo.ContextName = CommandsRegistry.DefaultContextName; inputBindingInfo.ContextName = CommandsRegistry.DefaultContextName;
inputBindingInfo.RoutedCommandName = routedCommandName; inputBindingInfo.RoutedCommandName = routedCommandName;
inputBindingInfo.Gestures = gestures; inputBindingInfo.Gestures = gestures;
inputBindingInfo.CategoryName = "Views"; inputBindingInfo.Categories.AddRange(CommandsRegistry.RegisterInputBindingCategories("Menu Items/Views"));
inputBindingInfo.AddIn = addIn; inputBindingInfo.AddIn = addIn;
CommandsRegistry.RegisterInputBinding(inputBindingInfo); CommandsRegistry.RegisterInputBinding(inputBindingInfo);

79
src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs

@ -5,6 +5,8 @@ using System.Windows;
using ICSharpCode.Core; using ICSharpCode.Core;
using System.Threading; using System.Threading;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
namespace ICSharpCode.Core.Presentation namespace ICSharpCode.Core.Presentation
{ {
@ -39,6 +41,8 @@ namespace ICSharpCode.Core.Presentation
private static Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>> commandBindingsUpdateHandlers = new Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>>(); private static Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>> commandBindingsUpdateHandlers = new Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>>();
private static Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>> inputBindingsUpdateHandlers = new Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>>(); private static Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>> inputBindingsUpdateHandlers = new Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>>();
private static List<InputBindingCategory> categories = new List<InputBindingCategory>();
/// <summary> /// <summary>
/// Get reference to routed UI command by name /// Get reference to routed UI command by name
/// </summary> /// </summary>
@ -110,12 +114,20 @@ namespace ICSharpCode.Core.Presentation
} }
} }
/// <summary>
/// Register input binding by specifying this binding parameters
/// </summary>
/// <param name="inputBindingInfo">Input binding parameters</param>
public static void RegisterInputBinding(InputBindingInfo inputBindingInfo) public static void RegisterInputBinding(InputBindingInfo inputBindingInfo)
{ {
inputBidnings.Add(inputBindingInfo); inputBidnings.Add(inputBindingInfo);
CommandsRegistry.InvokeCommandBindingUpdateHandlers(inputBindingInfo.ContextName, null); CommandsRegistry.InvokeCommandBindingUpdateHandlers(inputBindingInfo.ContextName, null);
} }
/// <summary>
/// Unregister input binding
/// </summary>
/// <param name="inputBindingInfo">Input binding parameters</param>
public static void UnregisterInputBinding(InputBindingInfo inputBindingInfo) public static void UnregisterInputBinding(InputBindingInfo inputBindingInfo)
{ {
inputBidnings.Remove(inputBindingInfo); inputBidnings.Remove(inputBindingInfo);
@ -129,7 +141,6 @@ namespace ICSharpCode.Core.Presentation
/// <param name="contextName">Context class full name</param> /// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Unregister binding assigned to specific context instance</param> /// <param name="contextInstance">Unregister binding assigned to specific context instance</param>
/// <param name="routedCommandName">Routed UI command name</param> /// <param name="routedCommandName">Routed UI command name</param>
/// <param name="gesture">Gesture</param>
public static ICollection<InputBindingInfo> FindInputBindingInfos(string contextName, UIElement contextInstance, string routedCommandName) { public static ICollection<InputBindingInfo> FindInputBindingInfos(string contextName, UIElement contextInstance, string routedCommandName) {
var foundBindings = new List<InputBindingInfo>(); var foundBindings = new List<InputBindingInfo>();
for(int i = inputBidnings.Count - 1; i >= 0; i--) { for(int i = inputBidnings.Count - 1; i >= 0; i--) {
@ -228,9 +239,9 @@ namespace ICSharpCode.Core.Presentation
} }
/// <summary> /// <summary>
/// Remove all managed input bindings from input bindings collection /// Remove all managed input bindings from <see cref="InputBindingCollection" />
/// </summary> /// </summary>
/// <param name="inputBindingCollection"></param> /// <param name="inputBindingCollection">Input binding cllection containing managed input bindings</param>
public static void RemoveManagedInputBindings(InputBindingCollection inputBindingCollection) { public static void RemoveManagedInputBindings(InputBindingCollection inputBindingCollection) {
for(int i = inputBindingCollection.Count - 1; i >= 0; i--) { for(int i = inputBindingCollection.Count - 1; i >= 0; i--) {
if(inputBindingCollection[i] is ManagedInputBinding) { if(inputBindingCollection[i] is ManagedInputBinding) {
@ -239,10 +250,18 @@ namespace ICSharpCode.Core.Presentation
} }
} }
/// <summary>
/// Register command binding by specifying command binding parameters
/// </summary>
/// <param name="commandBindingInfo">Command binding parameters</param>
public static void RegisterCommandBinding(CommandBindingInfo commandBindingInfo) { public static void RegisterCommandBinding(CommandBindingInfo commandBindingInfo) {
commandBindings.Add(commandBindingInfo); commandBindings.Add(commandBindingInfo);
} }
/// <summary>
/// Unregister command binding
/// </summary>
/// <param name="commandBindingInfo">Command binding parameters</param>
public static void UnregisterCommandBinding(CommandBindingInfo commandBindingInfo) { public static void UnregisterCommandBinding(CommandBindingInfo commandBindingInfo) {
commandBindings.Remove(commandBindingInfo); commandBindings.Remove(commandBindingInfo);
} }
@ -331,9 +350,9 @@ namespace ICSharpCode.Core.Presentation
} }
/// <summary> /// <summary>
/// Remove all managed command bindungs from command bindings collection /// Remove all managed command bindings from <see cref="CommandBindingCollection" />
/// </summary> /// </summary>
/// <param name="commandBindingsCollection"></param> /// <param name="commandBindingsCollection">Command binding cllection containing managed input bindings</param>
public static void RemoveManagedCommandBindings(CommandBindingCollection commandBindingsCollection) { public static void RemoveManagedCommandBindings(CommandBindingCollection commandBindingsCollection) {
for(int i = commandBindingsCollection.Count - 1; i >= 0; i--) { for(int i = commandBindingsCollection.Count - 1; i >= 0; i--) {
if(commandBindingsCollection[i] is ManagedCommandBinding) { if(commandBindingsCollection[i] is ManagedCommandBinding) {
@ -343,9 +362,9 @@ namespace ICSharpCode.Core.Presentation
} }
/// <summary> /// <summary>
/// Load all registered commands in addin /// Load all registered commands in add-in
/// </summary> /// </summary>
/// <param name="addIn">Addin</param> /// <param name="addIn">Add-in</param>
public static void LoadAddinCommands(AddIn addIn) { public static void LoadAddinCommands(AddIn addIn) {
foreach(var binding in commandBindings) { foreach(var binding in commandBindings) {
if(binding.AddIn != addIn) continue; if(binding.AddIn != addIn) continue;
@ -363,7 +382,8 @@ namespace ICSharpCode.Core.Presentation
} }
/// <summary> /// <summary>
/// Load command /// Register command object (either instance of <see cref="System.Windows.Input.ICommand" /> or <see cref="ICSharpCode.Core.ICommand" />)
/// which can be identified by command name
/// </summary> /// </summary>
/// <param name="commandName">Command name</param> /// <param name="commandName">Command name</param>
/// <param name="command">Command instance</param> /// <param name="command">Command instance</param>
@ -379,7 +399,7 @@ namespace ICSharpCode.Core.Presentation
} }
/// <summary> /// <summary>
/// Load context /// Register binding owner instance which can be identified by unique name
/// </summary> /// </summary>
/// <param name="contextName">Context class full name</param> /// <param name="contextName">Context class full name</param>
/// <param name="context">Context class instance</param> /// <param name="context">Context class instance</param>
@ -479,5 +499,46 @@ namespace ICSharpCode.Core.Presentation
return gestures; return gestures;
} }
/// <summary>
/// Register input binding category
///
/// Format:
/// , - Separates categories
/// / - Describes hierarchy meaning category to the left is child of the category to the right
///
/// <code>parent/child</code>
/// </summary>
/// <param name="categoriesString">String representing list of categories.</param>
/// <returns>Returns list of categories which can be assigned to input binding</returns>
public static List<InputBindingCategory> RegisterInputBindingCategories(string categoriesString) {
var registeredCategories = new List<InputBindingCategory>();
// Split categories
var categoryPaths = Regex.Split(categoriesString, @"\s*\,\s*");
foreach(var categoryPath in categoryPaths) {
// Split category path
var pathEntries = Regex.Split(categoryPath, @"\s*\/\s*").ToList();
var accumulatedPath = "";
InputBindingCategory parentCategory = null;
// In a loop create category hierarchy specified in a path
foreach(var categoryPathEntry in pathEntries) {
accumulatedPath += "/" + categoryPathEntry;
var matchingCategory = categories.FirstOrDefault(c => c.Path == accumulatedPath);
if(matchingCategory == null) {
matchingCategory = new InputBindingCategory(categoryPathEntry, parentCategory);
matchingCategory.Path = accumulatedPath;
categories.Add(matchingCategory);
}
parentCategory = matchingCategory;
}
registeredCategories.Add(parentCategory);
}
return registeredCategories;
}
} }
} }

4
src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs

@ -70,7 +70,7 @@ namespace ICSharpCode.Core.Presentation
} }
if(!string.IsNullOrEmpty(desc.Category)) { if(!string.IsNullOrEmpty(desc.Category)) {
inputBindingInfo.CategoryName = desc.Category; inputBindingInfo.Categories.AddRange(CommandsRegistry.RegisterInputBindingCategories(desc.Category));
} }
CommandsRegistry.RegisterInputBinding(inputBindingInfo); CommandsRegistry.RegisterInputBinding(inputBindingInfo);
@ -96,7 +96,7 @@ namespace ICSharpCode.Core.Presentation
} }
if(!string.IsNullOrEmpty(desc.Category)) { if(!string.IsNullOrEmpty(desc.Category)) {
inputBindingInfo.CategoryName = desc.Category; inputBindingInfo.Categories.AddRange(CommandsRegistry.RegisterInputBindingCategories(desc.Category));
} }
CommandsRegistry.RegisterInputBinding(inputBindingInfo); CommandsRegistry.RegisterInputBinding(inputBindingInfo);

47
src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingCategory.cs

@ -0,0 +1,47 @@
using System;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Stores input binding category description
/// </summary>
public class InputBindingCategory
{
/// <summary>
/// Creates new instance of <see cref="InputBindingCategory" />
/// </summary>
/// <param name="name">Category name</param>
/// <param name="parentCategory">Parent category (null - root level category)</param>
public InputBindingCategory(string name, InputBindingCategory parentCategory)
{
Name = name;
ParentCategory = parentCategory;
}
/// <summary>
/// Category name
/// </summary>
public string Name
{
get; set;
}
/// <summary>
/// Reference to parent category
/// </summary>
public InputBindingCategory ParentCategory
{
get; set;
}
/// <summary>
/// Category path is used to specify hierarchical category position
///
/// Format:
/// /category/subcategory
/// </summary>
internal string Path {
get; set;
}
}
}

6
src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Collections.Generic;
namespace ICSharpCode.Core.Presentation namespace ICSharpCode.Core.Presentation
{ {
@ -13,6 +14,7 @@ namespace ICSharpCode.Core.Presentation
public InputBindingInfo() { public InputBindingInfo() {
ContextName = CommandsRegistry.DefaultContextName; ContextName = CommandsRegistry.DefaultContextName;
Categories = new List<InputBindingCategory>();
} }
/// <summary> /// <summary>
@ -90,8 +92,8 @@ namespace ICSharpCode.Core.Presentation
get; set; get; set;
} }
public string CategoryName { public List<InputBindingCategory> Categories {
get; set; get; private set;
} }
} }
} }

1
src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj

@ -71,6 +71,7 @@
<Compile Include="CommandsService\CommandsService.cs" /> <Compile Include="CommandsService\CommandsService.cs" />
<Compile Include="CommandsService\CommandsRegistry.cs" /> <Compile Include="CommandsService\CommandsRegistry.cs" />
<Compile Include="CommandsService\GesturePlaceHolderRegistry.cs" /> <Compile Include="CommandsService\GesturePlaceHolderRegistry.cs" />
<Compile Include="CommandsService\InputBindingCategory.cs" />
<Compile Include="CommandsService\InputBindingInfo.cs" /> <Compile Include="CommandsService\InputBindingInfo.cs" />
<Compile Include="CommandsService\InputGestureCollectionConverter.cs" /> <Compile Include="CommandsService\InputGestureCollectionConverter.cs" />
<Compile Include="CommandsService\InputGestureCollectionExtensions.cs" /> <Compile Include="CommandsService\InputGestureCollectionExtensions.cs" />

2
src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs

@ -153,7 +153,7 @@ namespace ICSharpCode.Core.Presentation
var shortcut = codon.Properties["shortcut"]; var shortcut = codon.Properties["shortcut"];
var inputBindingInfo = new InputBindingInfo(); var inputBindingInfo = new InputBindingInfo();
inputBindingInfo.AddIn = codon.AddIn; inputBindingInfo.AddIn = codon.AddIn;
inputBindingInfo.CategoryName = "Menu items"; inputBindingInfo.Categories.AddRange(CommandsRegistry.RegisterInputBindingCategories("Menu Items"));
inputBindingInfo.ContextName = CommandsRegistry.DefaultContextName; inputBindingInfo.ContextName = CommandsRegistry.DefaultContextName;
inputBindingInfo.RoutedCommandName = routedCommandName; inputBindingInfo.RoutedCommandName = routedCommandName;
inputBindingInfo.Gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromInvariantString(codon.Properties["gestures"]); inputBindingInfo.Gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromInvariantString(codon.Properties["gestures"]);

Loading…
Cancel
Save