Browse Source

TextArea input bindings, input binding groups and search using BindingInfoTemplate (one unit test is broken)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/shortcuts@4502 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts^2
Sergej Andrejev 16 years ago
parent
commit
a467f466cc
  1. 1
      AddIns/ICSharpCode.SharpDevelop.addin
  2. 75
      src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplaceDialog.cs
  3. 8
      src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.addin
  4. 4
      src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj
  5. 7
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsManagementOptionsPanel.xaml.cs
  6. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
  7. 15
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretNavigationCommandHandler.cs
  8. 27
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs
  9. 74
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs
  10. 35
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaInputHandler.cs
  11. 13
      src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
  12. 4
      src/Main/Core/Project/Src/Util/ExtensionMethods.cs
  13. 117
      src/Main/ICSharpCode.Core.Presentation/CommandsService/BindingGroup.cs
  14. 33
      src/Main/ICSharpCode.Core.Presentation/CommandsService/BindingGroupCollection.cs
  15. 48
      src/Main/ICSharpCode.Core.Presentation/CommandsService/BindingInfoTemplate.cs
  16. 48
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs
  17. 361
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandManager.cs
  18. 4
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs
  19. 65
      src/Main/ICSharpCode.Core.Presentation/CommandsService/IBindingInfo.cs
  20. 172
      src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs
  21. 131
      src/Main/ICSharpCode.Core.Presentation/CommandsService/ObservableInputGestureCollection.cs
  22. 81
      src/Main/ICSharpCode.Core.Presentation/CommandsService/UserDefinedGesturesManager.cs
  23. 25
      src/Main/ICSharpCode.Core.Presentation/CommandsService/UserGesturesProfile.cs
  24. 3
      src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
  25. 19
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs

1
AddIns/ICSharpCode.SharpDevelop.addin

@ -124,7 +124,6 @@
<RoutedUICommand name="SDDebugCommands.StepOut" text="${res:XML.MainMenu.DebugMenu.StepOut}" /> <RoutedUICommand name="SDDebugCommands.StepOut" text="${res:XML.MainMenu.DebugMenu.StepOut}" />
<RoutedUICommand name="SDDebugCommands.ToggleBreakpoint" text="${res:XML.MainMenu.DebugMenu.ToggleBreakpoint}" /> <RoutedUICommand name="SDDebugCommands.ToggleBreakpoint" text="${res:XML.MainMenu.DebugMenu.ToggleBreakpoint}" />
<RoutedUICommand name="SDSearchCommands.ToggleBookmark" text="${res:XML.MainMenu.SearchMenu.ToggleBookmark}" /> <RoutedUICommand name="SDSearchCommands.ToggleBookmark" text="${res:XML.MainMenu.SearchMenu.ToggleBookmark}" />
<RoutedUICommand name="SDSearchCommands.PrevBookmark" text="${res:XML.MainMenu.SearchMenu.PrevBookmark}" /> <RoutedUICommand name="SDSearchCommands.PrevBookmark" text="${res:XML.MainMenu.SearchMenu.PrevBookmark}" />
<RoutedUICommand name="SDSearchCommands.NextBookmark" text="${res:XML.MainMenu.SearchMenu.NextBookmark}" /> <RoutedUICommand name="SDSearchCommands.NextBookmark" text="${res:XML.MainMenu.SearchMenu.NextBookmark}" />

75
src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchAndReplaceDialog.cs

@ -8,12 +8,16 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Input;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms; using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.Core.Presentation;
using SDCommandManager = ICSharpCode.Core.Presentation.CommandManager;
namespace SearchAndReplace namespace SearchAndReplace
{ {
public enum SearchAndReplaceMode { public enum SearchAndReplaceMode {
@ -87,16 +91,12 @@ namespace SearchAndReplace
SetSearchAndReplaceMode(); SetSearchAndReplaceMode();
FormLocationHelper.Apply(this, "ICSharpCode.SharpDevelop.Gui.SearchAndReplaceDialog.Location", false); FormLocationHelper.Apply(this, "ICSharpCode.SharpDevelop.Gui.SearchAndReplaceDialog.Location", false);
// Register shortcuts in "search & replace" dialog // TODO: Check how this realy should work
GesturePlaceHolderRegistry.RegisterUpdateHandler("SDSearchAndReplace.Find", delegate { var searchKeys = GetKeyBoardShortcut("SDSearchAndReplace.Find");
searchKeyboardShortcut = GesturePlaceHolderRegistry.GetGestures("SDSearchAndReplace.Find")[0]; searchKeyboardShortcut = searchKeys.Length > 0 ? searchKeys[0] : Keys.None;
});
GesturePlaceHolderRegistry.RegisterUpdateHandler("SDSearchAndReplace.Replace", delegate {
replaceKeyboardShortcut = GesturePlaceHolderRegistry.GetGestures("SDSearchAndReplace.Find")[0];
});
GesturePlaceHolderRegistry.InvokeUpdateHandlers("SDSearchAndReplace.Find"); var replaceKeys = GetKeyBoardShortcut("SDSearchAndReplace.Replace");
GesturePlaceHolderRegistry.InvokeUpdateHandlers("SDSearchAndReplace.FindReplace"); replaceKeyboardShortcut = replaceKeys.Length > 0 ? replaceKeys[0] : Keys.None;
} }
protected override void OnClosing(System.ComponentModel.CancelEventArgs e) protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
@ -105,7 +105,7 @@ namespace SearchAndReplace
Instance = null; Instance = null;
} }
protected override void OnKeyDown(KeyEventArgs e) protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
{ {
if (e.KeyData == Keys.Escape) { if (e.KeyData == Keys.Escape) {
Close(); Close();
@ -162,7 +162,62 @@ namespace SearchAndReplace
} }
} }
} }
return new Keys[] { Keys.None }; return new Keys[] { Keys.None };
} }
Keys[] GetKeyBoardShortcut(string routedCommandName)
{
var gestureCollection = SDCommandManager.FindInputGestures(new BindingInfoTemplate { RoutedCommandName = routedCommandName});
var keyCollection = new Keys[gestureCollection.Count];
var i = 0;
foreach(InputGesture gesture in gestureCollection) {
var keyGesture = gesture as KeyGesture;
if(!(keyGesture is MultiKeyGesture)) { // I can't imagine presenting these in WinForms
keyCollection[i++] = ConvertInputGestureToKeys(keyGesture);
}
}
return keyCollection;
}
Keys ConvertInputGestureToKeys(KeyGesture gesture)
{
var formsKey = Keys.None;
var key = Key.None;
var modifiers = System.Windows.Input.ModifierKeys.None;
var partialGesture = gesture as PartialKeyGesture;
var multiKeyGesture = gesture as MultiKeyGesture;
if(partialGesture != null) {
key = partialGesture.Key;
modifiers = partialGesture.Modifiers;
} else if(!(gesture is MultiKeyGesture)) {
key = gesture.Key;
modifiers = gesture.Modifiers;
}
if(key != Key.None || modifiers != System.Windows.Input.ModifierKeys.None) {
formsKey |= (Keys)KeyInterop.VirtualKeyFromKey(key);
if((modifiers & System.Windows.Input.ModifierKeys.Alt) == System.Windows.Input.ModifierKeys.Alt) {
formsKey |= Keys.Alt;
}
if((modifiers & System.Windows.Input.ModifierKeys.Control) == System.Windows.Input.ModifierKeys.Control) {
formsKey |= Keys.Control;
}
if((modifiers & System.Windows.Input.ModifierKeys.Shift) == System.Windows.Input.ModifierKeys.Shift) {
formsKey |= Keys.Shift;
}
// What about "Windows" key?
}
return formsKey;
}
} }
} }

8
src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.addin

@ -12,14 +12,14 @@
</Runtime> </Runtime>
<!-- Commands registry test --> <!-- Commands registry test -->
<Path name="/SharpDevelop/Workbench/RoutedUICommands"> <Path name="/SharpDevelop/CommandManager/RoutedUICommands">
<RoutedUICommand name="SDSearchAndReplace.Find" text="${res:XML.MainMenu.SearchMenu.Find}" /> <RoutedUICommand name="SDSearchAndReplace.Find" text="${res:XML.MainMenu.SearchMenu.Find}" />
<RoutedUICommand name="SDSearchAndReplace.FindNext" text="${res:XML.MainMenu.SearchMenu.FindNext}" /> <RoutedUICommand name="SDSearchAndReplace.FindNext" text="${res:XML.MainMenu.SearchMenu.FindNext}" />
<RoutedUICommand name="SDSearchAndReplace.FindNextSelected" text="${res:XML.MainMenu.SearchMenu.FindNextSelected}" /> <RoutedUICommand name="SDSearchAndReplace.FindNextSelected" text="${res:XML.MainMenu.SearchMenu.FindNextSelected}" />
<RoutedUICommand name="SDSearchAndReplace.Replace" text="${res:XML.MainMenu.SearchMenu.Replace}" /> <RoutedUICommand name="SDSearchAndReplace.Replace" text="${res:XML.MainMenu.SearchMenu.Replace}" />
</Path> </Path>
<Path name="/SharpDevelop/Workbench/CommandBindings"> <Path name="/SharpDevelop/CommandManager/CommandBindings">
<CommandBinding command="SDSearchAndReplace.Find" class="SearchAndReplace.Find" lazy="true" gestures="Ctrl+F" /> <CommandBinding command="SDSearchAndReplace.Find" class="SearchAndReplace.Find" lazy="true" gestures="Ctrl+F" />
<CommandBinding command="SDSearchAndReplace.FindNext" class="SearchAndReplace.FindNext" lazy="true" gestures="F3" /> <CommandBinding command="SDSearchAndReplace.FindNext" class="SearchAndReplace.FindNext" lazy="true" gestures="F3" />
<CommandBinding command="SDSearchAndReplace.FindNextSelected" class="SearchAndReplace.FindNextSelected" lazy="true" gestures="Ctrl+F3" /> <CommandBinding command="SDSearchAndReplace.FindNextSelected" class="SearchAndReplace.FindNextSelected" lazy="true" gestures="Ctrl+F3" />
@ -27,10 +27,6 @@
</Path> </Path>
<!-- Commands registry test --> <!-- Commands registry test -->
<Path name="/SharpDevelop/Workbench/GesturePlaceHolder">
<GesturesPlaceHolder name="SDSearchAndReplace.Find" text="Find next" gestures="Ctrl+F" />
<GesturesPlaceHolder name="SDSearchAndReplace.Replace" text="Find next" gestures="F3" />
</Path>
<Path name = "/SharpDevelop/Workbench/MainMenu/Search"> <Path name = "/SharpDevelop/Workbench/MainMenu/Search">

4
src/AddIns/Misc/SearchAndReplace/Project/SearchAndReplace.csproj

@ -127,6 +127,10 @@
<Name>ICSharpCode.Core</Name> <Name>ICSharpCode.Core</Name>
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj">
<Project>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</Project>
<Name>ICSharpCode.Core.Presentation</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj"> <ProjectReference Include="..\..\..\..\Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj">
<Project>{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}</Project> <Project>{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}</Project>
<Name>ICSharpCode.Core.WinForms</Name> <Name>ICSharpCode.Core.WinForms</Name>

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

@ -193,7 +193,7 @@ namespace ICSharpCode.ShortcutsManagement.Dialogs
} }
} }
var inputBindingInfos = CommandManager.FindInputBindingInfos(null, null, null, null); var inputBindingInfos = CommandManager.FindInputBindingInfos(new BindingInfoTemplate());
foreach (var inputBindingInfo in inputBindingInfos) foreach (var inputBindingInfo in inputBindingInfos)
{ {
// Get shortcut entry text. Normaly shortcut entry text is equal to routed command text // Get shortcut entry text. Normaly shortcut entry text is equal to routed command text
@ -210,7 +210,7 @@ namespace ICSharpCode.ShortcutsManagement.Dialogs
// Strip this sign from shortcut entry text // Strip this sign from shortcut entry text
shortcutText = Regex.Replace(shortcutText, @"&([^\s])", @"$1"); shortcutText = Regex.Replace(shortcutText, @"&([^\s])", @"$1");
var shortcutGestures = new InputGestureCollection(inputBindingInfo.DefaultGestures); var shortcutGestures = inputBindingInfo.DefaultGestures.GetInputGestureCollection();
if(SelectedProfile != null && SelectedProfile[inputBindingInfo.Identifier] != null) { if(SelectedProfile != null && SelectedProfile[inputBindingInfo.Identifier] != null) {
shortcutGestures = new InputGestureCollection(SelectedProfile[inputBindingInfo.Identifier]); shortcutGestures = new InputGestureCollection(SelectedProfile[inputBindingInfo.Identifier]);
} }
@ -254,10 +254,7 @@ namespace ICSharpCode.ShortcutsManagement.Dialogs
} }
} }
shortcutsMap.ForEach(b => b.Value.IsModifyed = true);
UserDefinedGesturesManager.CurrentProfile = SelectedProfile; UserDefinedGesturesManager.CurrentProfile = SelectedProfile;
CommandManager.InvokeInputBindingUpdateHandlers();
profiles.ForEach(p => p.Save()); profiles.ForEach(p => p.Save());

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj

@ -82,6 +82,10 @@
<ItemGroup> <ItemGroup>
<Folder Include="Document" /> <Folder Include="Document" />
<Folder Include="Utils" /> <Folder Include="Utils" />
<ProjectReference Include="..\..\..\Main\ICSharpCode.Core.Presentation\Test\ICSharpCode.Core.Presentation.Tests.csproj">
<Project>{FFA7988E-7348-4669-9E9D-27E629C873A2}</Project>
<Name>ICSharpCode.Core.Presentation.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj"> <ProjectReference Include="..\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project> <Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Name>ICSharpCode.AvalonEdit</Name> <Name>ICSharpCode.AvalonEdit</Name>

15
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretNavigationCommandHandler.cs

@ -23,7 +23,10 @@ namespace ICSharpCode.AvalonEdit.Editing
{ {
static class CaretNavigationCommandHandler static class CaretNavigationCommandHandler
{ {
static BindingGroup bindingGroup; public static BindingGroup ClassWideBindingGroup
{
get; private set;
}
/// <summary> /// <summary>
/// Creates a new <see cref="TextAreaInputHandler"/> for the text area. /// Creates a new <see cref="TextAreaInputHandler"/> for the text area.
@ -31,7 +34,7 @@ namespace ICSharpCode.AvalonEdit.Editing
public static TextAreaInputHandler Create(TextArea textArea) public static TextAreaInputHandler Create(TextArea textArea)
{ {
TextAreaInputHandler handler = new TextAreaInputHandler(textArea); TextAreaInputHandler handler = new TextAreaInputHandler(textArea);
handler.BindingGroup = bindingGroup; handler.BindingGroup = ClassWideBindingGroup;
// TODO: DELETE // TODO: DELETE
// handler.CommandBindings.AddRange(CommandBindings); // handler.CommandBindings.AddRange(CommandBindings);
@ -53,8 +56,8 @@ namespace ICSharpCode.AvalonEdit.Editing
{ {
var inputBinding = new InputBindingInfo(); var inputBinding = new InputBindingInfo();
inputBinding.OwnerTypeName = typeof(TextArea).GetShortAssemblyQualifiedName(); inputBinding.OwnerTypeName = typeof(TextArea).GetShortAssemblyQualifiedName();
inputBinding.DefaultGestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFrom(gesturesString); inputBinding.DefaultGestures.AddRange((InputGestureCollection)new InputGestureCollectionConverter().ConvertFrom(gesturesString));
inputBinding.Groups.Add(bindingGroup); inputBinding.Groups.Add(ClassWideBindingGroup);
inputBinding.RoutedCommandName = routedCommandName; inputBinding.RoutedCommandName = routedCommandName;
SDCommandManager.RegisterInputBinding(inputBinding); SDCommandManager.RegisterInputBinding(inputBinding);
} }
@ -66,14 +69,14 @@ namespace ICSharpCode.AvalonEdit.Editing
commandBinding.ExecutedEventHandler = executedHandler; commandBinding.ExecutedEventHandler = executedHandler;
commandBinding.CanExecuteEventHandler = canExecuteHandler; commandBinding.CanExecuteEventHandler = canExecuteHandler;
commandBinding.IsLazy = false; commandBinding.IsLazy = false;
commandBinding.Groups.Add(bindingGroup); commandBinding.Groups.Add(ClassWideBindingGroup);
commandBinding.RoutedCommandName = routedCommandName; commandBinding.RoutedCommandName = routedCommandName;
SDCommandManager.RegisterCommandBinding(commandBinding); SDCommandManager.RegisterCommandBinding(commandBinding);
} }
static CaretNavigationCommandHandler() static CaretNavigationCommandHandler()
{ {
bindingGroup = new BindingGroup(); ClassWideBindingGroup = new BindingGroup();
AddBinding("EditingCommands.MoveLeftByCharacter", "Left", null, OnMoveCaret(CaretMovementType.CharLeft)); AddBinding("EditingCommands.MoveLeftByCharacter", "Left", null, OnMoveCaret(CaretMovementType.CharLeft));
AddBinding("EditingCommands.SelectLeftByCharacter", "Shift+Left", null, OnMoveCaretExtendSelection(CaretMovementType.CharLeft)); AddBinding("EditingCommands.SelectLeftByCharacter", "Shift+Left", null, OnMoveCaretExtendSelection(CaretMovementType.CharLeft));

27
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs

@ -31,7 +31,10 @@ namespace ICSharpCode.AvalonEdit.Editing
/// </summary> /// </summary>
static class EditingCommandHandler static class EditingCommandHandler
{ {
static BindingGroup bindingGroup; public static BindingGroup ClassWideBindingGroup
{
get; private set;
}
/// <summary> /// <summary>
/// Creates a new <see cref="TextAreaInputHandler"/> for the text area. /// Creates a new <see cref="TextAreaInputHandler"/> for the text area.
@ -39,19 +42,7 @@ namespace ICSharpCode.AvalonEdit.Editing
public static TextAreaInputHandler Create(TextArea textArea) public static TextAreaInputHandler Create(TextArea textArea)
{ {
TextAreaInputHandler handler = new TextAreaInputHandler(textArea); TextAreaInputHandler handler = new TextAreaInputHandler(textArea);
handler.BindingGroup = bindingGroup; handler.BindingGroup = ClassWideBindingGroup;
// TODO: REMOVE
// var groups = new BindingGroupCollection { bindingGroup };
// var commandBindings = SDCommandManager.FindCommandBindings(null, null, null, groups);
// handler.CommandBindings.AddRange(commandBindings.Cast<CommandBinding>()); // Todo: fix later
// var inputBindings = SDCommandManager.FindInputBindings(null, null, null, groups);
// handler.InputBindings.AddRange(inputBindings.Cast<InputBinding>()); // Todo: fix later
return handler; return handler;
} }
@ -69,8 +60,8 @@ namespace ICSharpCode.AvalonEdit.Editing
{ {
var inputBinding = new InputBindingInfo(); var inputBinding = new InputBindingInfo();
inputBinding.OwnerTypeName = typeof(TextArea).GetShortAssemblyQualifiedName(); inputBinding.OwnerTypeName = typeof(TextArea).GetShortAssemblyQualifiedName();
inputBinding.DefaultGestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFrom(gesturesString); inputBinding.DefaultGestures.AddRange((InputGestureCollection)new InputGestureCollectionConverter().ConvertFrom(gesturesString));
inputBinding.Groups.Add(bindingGroup); inputBinding.Groups.Add(ClassWideBindingGroup);
inputBinding.Categories.AddRange(SDCommandManager.GetInputBindingCategoryCollection("/MainMenu/Edit", true)); inputBinding.Categories.AddRange(SDCommandManager.GetInputBindingCategoryCollection("/MainMenu/Edit", true));
inputBinding.RoutedCommandName = routedCommandName; inputBinding.RoutedCommandName = routedCommandName;
SDCommandManager.RegisterInputBinding(inputBinding); SDCommandManager.RegisterInputBinding(inputBinding);
@ -83,14 +74,14 @@ namespace ICSharpCode.AvalonEdit.Editing
commandBinding.ExecutedEventHandler = executedHandler; commandBinding.ExecutedEventHandler = executedHandler;
commandBinding.CanExecuteEventHandler = canExecuteHandler; commandBinding.CanExecuteEventHandler = canExecuteHandler;
commandBinding.IsLazy = false; commandBinding.IsLazy = false;
commandBinding.Groups.Add(bindingGroup); commandBinding.Groups.Add(ClassWideBindingGroup);
commandBinding.RoutedCommandName = routedCommandName; commandBinding.RoutedCommandName = routedCommandName;
SDCommandManager.RegisterCommandBinding(commandBinding); SDCommandManager.RegisterCommandBinding(commandBinding);
} }
static EditingCommandHandler() static EditingCommandHandler()
{ {
bindingGroup = new BindingGroup(); ClassWideBindingGroup = new BindingGroup();
AddCommandBinding("ApplicationCommands.Delete", CanDelete, OnDelete(ApplicationCommands.NotACommand)); AddCommandBinding("ApplicationCommands.Delete", CanDelete, OnDelete(ApplicationCommands.NotACommand));
AddBinding("EditingCommands.Delete", "Delete", null, OnDelete(EditingCommands.SelectRightByCharacter)); AddBinding("EditingCommands.Delete", "Delete", null, OnDelete(EditingCommands.SelectRightByCharacter));

74
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs

@ -8,6 +8,8 @@
using System; using System;
using System.Windows.Input; using System.Windows.Input;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.Core.Presentation;
using SDCommandManager=ICSharpCode.Core.Presentation.CommandManager;
namespace ICSharpCode.AvalonEdit.Editing namespace ICSharpCode.AvalonEdit.Editing
{ {
@ -31,32 +33,76 @@ namespace ICSharpCode.AvalonEdit.Editing
/// </summary> /// </summary>
public ITextAreaInputHandler MouseSelection { get; private set; } public ITextAreaInputHandler MouseSelection { get; private set; }
public static BindingGroup ClassWideBindingGroup
{
get; private set;
}
static TextAreaDefaultInputHandler()
{
ClassWideBindingGroup = new BindingGroup();
AddCommandBinding("ApplicationCommands.Undo", CanExecuteUndo, ExecuteUndo);
AddCommandBinding("ApplicationCommands.Redo", CanExecuteRedo, ExecuteRedo);
}
static void AddBinding(string routedCommandName, string gesturesString, CanExecuteRoutedEventHandler canExecuteHandler, ExecutedRoutedEventHandler executedHandler)
{
AddCommandBinding(routedCommandName, canExecuteHandler, executedHandler);
AddInputBinding(routedCommandName, gesturesString);
}
static void AddInputBinding(string routedCommandName, string gesturesString)
{
var inputBinding = new InputBindingInfo();
inputBinding.OwnerTypeName = typeof(TextArea).GetShortAssemblyQualifiedName();
inputBinding.DefaultGestures.AddRange((InputGestureCollection)new InputGestureCollectionConverter().ConvertFrom(gesturesString));
inputBinding.Groups.Add(ClassWideBindingGroup);
inputBinding.Categories.AddRange(SDCommandManager.GetInputBindingCategoryCollection("/MainMenu/Edit", true));
inputBinding.RoutedCommandName = routedCommandName;
SDCommandManager.RegisterInputBinding(inputBinding);
}
static void AddCommandBinding(string routedCommandName, CanExecuteRoutedEventHandler canExecuteHandler, ExecutedRoutedEventHandler executedHandler)
{
var commandBinding = new CommandBindingInfo();
commandBinding.OwnerTypeName = typeof(TextArea).GetShortAssemblyQualifiedName();
commandBinding.ExecutedEventHandler = executedHandler;
commandBinding.CanExecuteEventHandler = canExecuteHandler;
commandBinding.IsLazy = false;
commandBinding.Groups.Add(ClassWideBindingGroup);
commandBinding.RoutedCommandName = routedCommandName;
SDCommandManager.RegisterCommandBinding(commandBinding);
}
/// <summary> /// <summary>
/// Creates a new TextAreaDefaultInputHandler instance. /// Creates a new TextAreaDefaultInputHandler instance.
/// </summary> /// </summary>
public TextAreaDefaultInputHandler(TextArea textArea) : base(textArea) public TextAreaDefaultInputHandler(TextArea textArea) : base(textArea)
{ {
BindingGroup = ClassWideBindingGroup;
this.NestedInputHandlers.Add(CaretNavigation = CaretNavigationCommandHandler.Create(textArea)); this.NestedInputHandlers.Add(CaretNavigation = CaretNavigationCommandHandler.Create(textArea));
this.NestedInputHandlers.Add(Editing = EditingCommandHandler.Create(textArea)); this.NestedInputHandlers.Add(Editing = EditingCommandHandler.Create(textArea));
this.NestedInputHandlers.Add(MouseSelection = new SelectionMouseHandler(textArea)); this.NestedInputHandlers.Add(MouseSelection = new SelectionMouseHandler(textArea));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, ExecuteUndo, CanExecuteUndo)); // TODO: DELETE
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, ExecuteRedo, CanExecuteRedo));
// this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, ExecuteUndo, CanExecuteUndo));
// this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, ExecuteRedo, CanExecuteRedo));
} }
#region Undo / Redo #region Undo / Redo
UndoStack GetUndoStack() static UndoStack GetUndoStack(TextArea textArea)
{ {
TextDocument document = this.TextArea.Document; if (textArea != null && textArea.Document != null)
if (document != null) return textArea.Document.UndoStack;
return document.UndoStack;
else else
return null; return null;
} }
void ExecuteUndo(object sender, ExecutedRoutedEventArgs e) static void ExecuteUndo(object sender, ExecutedRoutedEventArgs e)
{ {
var undoStack = GetUndoStack(); var undoStack = GetUndoStack(sender as TextArea);
if (undoStack != null) { if (undoStack != null) {
if (undoStack.CanUndo) if (undoStack.CanUndo)
undoStack.Undo(); undoStack.Undo();
@ -64,18 +110,18 @@ namespace ICSharpCode.AvalonEdit.Editing
} }
} }
void CanExecuteUndo(object sender, CanExecuteRoutedEventArgs e) static void CanExecuteUndo(object sender, CanExecuteRoutedEventArgs e)
{ {
var undoStack = GetUndoStack(); var undoStack = GetUndoStack(sender as TextArea);
if (undoStack != null) { if (undoStack != null) {
e.Handled = true; e.Handled = true;
e.CanExecute = undoStack.CanUndo; e.CanExecute = undoStack.CanUndo;
} }
} }
void ExecuteRedo(object sender, ExecutedRoutedEventArgs e) static void ExecuteRedo(object sender, ExecutedRoutedEventArgs e)
{ {
var undoStack = GetUndoStack(); var undoStack = GetUndoStack(sender as TextArea);
if (undoStack != null) { if (undoStack != null) {
if (undoStack.CanRedo) if (undoStack.CanRedo)
undoStack.Redo(); undoStack.Redo();
@ -83,9 +129,9 @@ namespace ICSharpCode.AvalonEdit.Editing
} }
} }
void CanExecuteRedo(object sender, CanExecuteRoutedEventArgs e) static void CanExecuteRedo(object sender, CanExecuteRoutedEventArgs e)
{ {
var undoStack = GetUndoStack(); var undoStack = GetUndoStack(sender as TextArea);
if (undoStack != null) { if (undoStack != null) {
e.Handled = true; e.Handled = true;
e.CanExecute = undoStack.CanRedo; e.CanExecute = undoStack.CanRedo;

35
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaInputHandler.cs

@ -51,14 +51,14 @@ namespace ICSharpCode.AvalonEdit.Editing
readonly TextArea textArea; readonly TextArea textArea;
bool isAttached; bool isAttached;
private BindingGroup m_bindingGroup; private BindingGroup _bindingGroup;
public BindingGroup BindingGroup public BindingGroup BindingGroup
{ {
get { get {
return m_bindingGroup; return _bindingGroup;
} }
set { set {
m_bindingGroup = value; _bindingGroup = value;
} }
} }
@ -179,12 +179,11 @@ namespace ICSharpCode.AvalonEdit.Editing
BindingGroup.AttachTo(textArea); BindingGroup.AttachTo(textArea);
} }
// TODO: REMOVE textArea.CommandBindings.AddRange(commandBindings);
textArea.InputBindings.AddRange(inputBindings);
// textArea.CommandBindings.AddRange(commandBindings); foreach (ITextAreaInputHandler handler in nestedInputHandlers)
// textArea.InputBindings.AddRange(inputBindings); handler.Attach();
//foreach (ITextAreaInputHandler handler in nestedInputHandlers)
// handler.Attach();
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -194,16 +193,20 @@ namespace ICSharpCode.AvalonEdit.Editing
throw new InvalidOperationException("Input handler is not attached"); throw new InvalidOperationException("Input handler is not attached");
isAttached = false; isAttached = false;
BindingGroup.DetachFrom(textArea); // Detach binding from textarea
if(BindingGroup != null) {
BindingGroup.DetachFrom(textArea);
}
// TODO: REMOVE // Detach binding to specified input and command bindings
foreach (CommandBinding b in commandBindings)
textArea.CommandBindings.Remove(b);
foreach (InputBinding b in inputBindings)
textArea.InputBindings.Remove(b);
// foreach (CommandBinding b in commandBindings) // Detach nested handlers
// textArea.CommandBindings.Remove(b); foreach (ITextAreaInputHandler handler in nestedInputHandlers)
// foreach (InputBinding b in inputBindings) handler.Detach();
// textArea.InputBindings.Remove(b);
// foreach (ITextAreaInputHandler handler in nestedInputHandlers)
// handler.Detach();
} }
#endregion #endregion
} }

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

@ -243,8 +243,12 @@ namespace ICSharpCode.SharpDevelop.Commands
CommandManager.RegisterInputBinding(inputBindingInfo); CommandManager.RegisterInputBinding(inputBindingInfo);
} }
var updatedGestures = CommandManager.FindInputGestures(CommandManager.DefaultContextName, null, routedCommandName, null); var gesturesTemplate = new BindingInfoTemplate();
gesturesTemplate.OwnerTypeName = CommandManager.DefaultContextName;
gesturesTemplate.RoutedCommandName = routedCommandName;
var updatedGestures = CommandManager.FindInputGestures(gesturesTemplate);
var updatedGesturesText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures); var updatedGesturesText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures);
items[i].InputGestureText = updatedGesturesText; items[i].InputGestureText = updatedGesturesText;
items[i].Command = CommandManager.GetRoutedUICommand(routedCommandName); items[i].Command = CommandManager.GetRoutedUICommand(routedCommandName);
items[i].Header = StringParser.Parse(tool.ToString()); items[i].Header = StringParser.Parse(tool.ToString());
@ -535,7 +539,7 @@ namespace ICSharpCode.SharpDevelop.Commands
var inputBindingInfo = new InputBindingInfo(); var inputBindingInfo = new InputBindingInfo();
inputBindingInfo.OwnerTypeName = CommandManager.DefaultContextName; inputBindingInfo.OwnerTypeName = CommandManager.DefaultContextName;
inputBindingInfo.RoutedCommandName = routedCommandName; inputBindingInfo.RoutedCommandName = routedCommandName;
inputBindingInfo.DefaultGestures = gestures; inputBindingInfo.DefaultGestures.AddRange(gestures);
var categoryPath = "/MainMenu/View" + (Category == padContent.Category && padContent.Category != "Main" ? "/" + padContent.Class : ""); var categoryPath = "/MainMenu/View" + (Category == padContent.Category && padContent.Category != "Main" ? "/" + padContent.Class : "");
@ -554,7 +558,10 @@ namespace ICSharpCode.SharpDevelop.Commands
item.Command = CommandManager.GetRoutedUICommand(routedCommandName); item.Command = CommandManager.GetRoutedUICommand(routedCommandName);
var updatedGestures = CommandManager.FindInputGestures(CommandManager.DefaultContextName, null, routedCommandName, null); var gesturesTemplate = new BindingInfoTemplate();
gesturesTemplate.OwnerTypeName = CommandManager.DefaultContextName;
gesturesTemplate.RoutedCommandName = routedCommandName;
var updatedGestures = CommandManager.FindInputGestures(gesturesTemplate);
var updatedGesturesText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures); var updatedGesturesText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures);
item.InputGestureText = updatedGesturesText; item.InputGestureText = updatedGesturesText;

4
src/Main/Core/Project/Src/Util/ExtensionMethods.cs

@ -19,6 +19,10 @@ namespace ICSharpCode.Core
/// <returns><code>true</code> if item is found; otherwise false</returns> /// <returns><code>true</code> if item is found; otherwise false</returns>
public static bool ContainsAnyFromCollection<T>(this ICollection<T> thisCollection, ICollection<T> otherCollection) public static bool ContainsAnyFromCollection<T>(this ICollection<T> thisCollection, ICollection<T> otherCollection)
{ {
if(otherCollection == null) {
throw new ArgumentNullException("otherCollection");
}
foreach(var thisCollectionItem in thisCollection) { foreach(var thisCollectionItem in thisCollection) {
if(otherCollection.Contains(thisCollectionItem)) { if(otherCollection.Contains(thisCollectionItem)) {
return true; return true;

117
src/Main/ICSharpCode.Core.Presentation/CommandsService/BindingGroup.cs

@ -1,11 +1,3 @@
/*
* Created by SharpDevelop.
* User: Administrator
* Date: 7/13/2009
* Time: 5:10 PM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -25,8 +17,7 @@ namespace ICSharpCode.Core.Presentation
private ObservableCollection<InputBindingInfo> _inputBindings; private ObservableCollection<InputBindingInfo> _inputBindings;
private ObservableCollection<CommandBindingInfo> _commandBindings; private ObservableCollection<CommandBindingInfo> _commandBindings;
private List<string> _attachedNamedInstances = new List<string>(); private HashSet<UIElement> _attachedInstances = new HashSet<UIElement>();
private List<UIElement> _attachedInstances = new List<UIElement>();
private List<BindingGroup> _nestedGroups = new List<BindingGroup>(); private List<BindingGroup> _nestedGroups = new List<BindingGroup>();
@ -44,89 +35,72 @@ namespace ICSharpCode.Core.Presentation
get; set; get; set;
} }
public bool IsAttachedTo(UIElement instance) public static bool IsActive(IBindingInfo bindingInfo)
{ {
return _attachedInstances.Contains(instance); if(bindingInfo.OwnerInstances != null && bindingInfo.Groups != null && bindingInfo.Groups.Count > 0) {
} return bindingInfo.Groups.IsAttachedToAny(bindingInfo.OwnerInstances);
}
public bool IsAttachedTo(string instanceName) return true;
{
return _attachedNamedInstances.Contains(instanceName);
} }
public void AttachTo(UIElement instance) public bool IsAttachedTo(UIElement instance)
{ {
if(!_attachedInstances.Contains(instance)) { return _attachedInstances.Contains(instance);
AttachToWithoutInvoke(instance);
}
} }
public void AttachTo(string instanceName) public void AttachTo(UIElement instance)
{ {
if(!_attachedNamedInstances.Contains(instanceName)) { AttachToWithoutInvoke(instance);
AttachToWithoutInvoke(instanceName); InvokeBindingUpdateHandlers(instance);
}
} }
private void AttachToWithoutInvoke(UIElement instance) private void AttachToWithoutInvoke(UIElement instance)
{ {
if(!_attachedInstances.Contains(instance)) { _attachedInstances.Add(instance);
_attachedInstances.Add(instance);
foreach(var nestedGroup in _nestedGroups) { foreach(var nestedGroup in _nestedGroups) {
nestedGroup.AttachToWithoutInvoke(instance); nestedGroup.AttachToWithoutInvoke(instance);
} }
}
} }
private void AttachToWithoutInvoke(string instanceName) public void DetachFromWithoutInvoke(UIElement instance)
{ {
if(!_attachedNamedInstances.Contains(instanceName)) { _attachedInstances.Remove(instance);
_attachedNamedInstances.Add(instanceName);
foreach(var nestedGroup in _nestedGroups) { foreach(var nestedGroup in _nestedGroups) {
nestedGroup.AttachToWithoutInvoke(instanceName); nestedGroup.DetachFrom(instance);
} }
}
} }
public void DetachFromWithoutInvoke(UIElement instance) public void DetachFrom(UIElement instance)
{ {
if(_attachedInstances.Contains(instance)) { DetachFromWithoutInvoke(instance);
_attachedInstances.Remove(instance); InvokeBindingUpdateHandlers(instance);
foreach(var nestedGroup in _nestedGroups) {
nestedGroup.DetachFrom(instance);
}
}
} }
public void DetachFromWithoutInvoke(string instanceName) private void InvokeBindingUpdateHandlers(UIElement instance)
{ {
if(_attachedNamedInstances.Contains(instanceName)) { var i = 0;
_attachedNamedInstances.Remove(instanceName);
foreach(var nestedGroup in _nestedGroups) { // Invoke class wide and instance update handlers
nestedGroup.DetachFrom(instanceName); var instanceNames = CommandManager.GetUIElementNameCollection(instance);
} var typeNames = CommandManager.GetUITypeNameCollection(instance.GetType());
}
}
public void DetachFrom(UIElement instance) var bindingInfoTemplates = new BindingInfoTemplate[instanceNames.Count + typeNames.Count + 2];
{ bindingInfoTemplates[i++] = new BindingInfoTemplate { OwnerInstances = new[] { instance }};
if(_attachedInstances.Contains(instance)) { bindingInfoTemplates[i++] = new BindingInfoTemplate { OwnerTypes = new[] { instance.GetType() }};
DetachFromWithoutInvoke(instance);
}
}
public void DetachFrom(string instanceName) foreach(var instanceName in instanceNames) {
{ bindingInfoTemplates[i++] = new BindingInfoTemplate { OwnerInstanceName = instanceName };
if(_attachedNamedInstances.Contains(instanceName)) { }
DetachFromWithoutInvoke(instanceName);
CommandManager.InvokeCommandBindingUpdateHandlers(null, instanceName); foreach(var typeName in typeNames) {
CommandManager.InvokeInputBindingUpdateHandlers(null, instanceName); bindingInfoTemplates[i++] = new BindingInfoTemplate { OwnerTypeName = typeName };
} }
CommandManager.InvokeCommandBindingUpdateHandlers(bindingInfoTemplates);
CommandManager.InvokeInputBindingUpdateHandlers(bindingInfoTemplates);
} }
public List<BindingGroup> NestedGroups public List<BindingGroup> NestedGroups
@ -139,22 +113,19 @@ namespace ICSharpCode.Core.Presentation
public ICollection<BindingGroup> FlatNestedGroups public ICollection<BindingGroup> FlatNestedGroups
{ {
get { get {
var foundNestedGroups = new List<BindingGroup>(); var foundNestedGroups = new HashSet<BindingGroup>();
FlattenNestedGroups(this, foundNestedGroups); FlattenNestedGroups(this, foundNestedGroups);
return foundNestedGroups.AsReadOnly(); return foundNestedGroups;
} }
} }
internal void FlattenNestedGroups(BindingGroup rootGroup, ICollection<BindingGroup> foundGroups) internal void FlattenNestedGroups(BindingGroup rootGroup, HashSet<BindingGroup> foundGroups)
{ {
if(!foundGroups.Contains(rootGroup)) { foundGroups.Add(rootGroup);
foundGroups.Add(rootGroup);
}
foreach(var nestedGroup in NestedGroups) { foreach(var nestedGroup in NestedGroups) {
if(!foundGroups.Contains(nestedGroup)) { if(foundGroups.Add(nestedGroup)) {
foundGroups.Add(nestedGroup);
FlattenNestedGroups(nestedGroup, foundGroups); FlattenNestedGroups(nestedGroup, foundGroups);
} }
} }

33
src/Main/ICSharpCode.Core.Presentation/CommandsService/BindingGroupCollection.cs

@ -1,16 +1,9 @@
/*
* Created by SharpDevelop.
* User: Administrator
* Date: 7/14/2009
* Time: 1:20 PM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Windows;
using ICSharpCode.Core; using ICSharpCode.Core;
@ -33,19 +26,22 @@ namespace ICSharpCode.Core.Presentation
public BindingGroupCollection FlatNesteGroups public BindingGroupCollection FlatNesteGroups
{ {
get { get {
var flatGroups = new BindingGroupCollection(); var flatGroups = new HashSet<BindingGroup>();
foreach(var bindingGroup in this) { foreach(var bindingGroup in this) {
bindingGroup.FlattenNestedGroups(bindingGroup, flatGroups); bindingGroup.FlattenNestedGroups(bindingGroup, flatGroups);
} }
return flatGroups; var flatBindingGroupCollection = new BindingGroupCollection();
flatBindingGroupCollection.AddRange(flatGroups);
return flatBindingGroupCollection;
} }
} }
public bool IsAttachedTo(string instanceName) public bool IsAttachedTo(UIElement instance)
{ {
foreach(var bindingGroup in FlatNesteGroups) { foreach(var bindingGroup in FlatNesteGroups) {
if(bindingGroup.IsAttachedTo(instanceName)) { if(bindingGroup.IsAttachedTo(instance)) {
return true; return true;
} }
} }
@ -53,6 +49,19 @@ namespace ICSharpCode.Core.Presentation
return false; return false;
} }
public bool IsAttachedToAny(ICollection<UIElement> instances)
{
if(instances != null && instances.Count > 0) {
foreach(var instance in instances) {
if(IsAttachedTo(instance)) {
return true;
}
}
}
return false;
}
public int Count { public int Count {
get { get {
return _bindingGroups.Count; return _bindingGroups.Count;

48
src/Main/ICSharpCode.Core.Presentation/CommandsService/BindingInfoTemplate.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Description of BindingInfoTemplate.
/// </summary>
public struct BindingInfoTemplate : IBindingInfo
{
public string OwnerInstanceName
{
get; set;
}
public ICollection<UIElement> OwnerInstances
{
get; set;
}
public string OwnerTypeName
{
get; set;
}
public ICollection<Type> OwnerTypes
{
get; set;
}
public string RoutedCommandName
{
get; set;
}
public RoutedUICommand RoutedCommand
{
get; set;
}
public BindingGroupCollection Groups
{
get; set;
}
}
}

48
src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs

@ -11,14 +11,13 @@ namespace ICSharpCode.Core.Presentation
/// <summary> /// <summary>
/// Stores details about <see cref="CommandBinding" /> /// Stores details about <see cref="CommandBinding" />
/// </summary> /// </summary>
public class CommandBindingInfo public class CommandBindingInfo : IBindingInfo
{ {
/// <summary> /// <summary>
/// Creates new instance of <see cref="CommandBindingInfo" /> /// Creates new instance of <see cref="CommandBindingInfo" />
/// </summary> /// </summary>
public CommandBindingInfo() public CommandBindingInfo()
{ {
IsModifyed = true;
OldCommandBindings = new CommandBindingCollection(); OldCommandBindings = new CommandBindingCollection();
ActiveCommandBindings = new CommandBindingCollection(); ActiveCommandBindings = new CommandBindingCollection();
@ -45,22 +44,18 @@ namespace ICSharpCode.Core.Presentation
get; private set; get; private set;
} }
public bool IsActive private string routedCommandName;
{
get {
if(OwnerInstanceName != null && Groups != null && Groups.Count > 0) {
return Groups.IsAttachedTo(OwnerInstanceName);
}
return true;
}
}
/// <summary> /// <summary>
/// Name of the routed command which will be invoked when this binding is triggered /// Name of the routed command which will be invoked when this binding is triggered
/// </summary> /// </summary>
public string RoutedCommandName { public string RoutedCommandName {
get; set; get {
return routedCommandName;
}
set {
routedCommandName = value;
}
} }
/// <summary> /// <summary>
@ -217,7 +212,7 @@ namespace ICSharpCode.Core.Presentation
public ICollection<UIElement> OwnerInstances { public ICollection<UIElement> OwnerInstances {
get { get {
if(_ownerInstanceName != null) { if(_ownerInstanceName != null) {
return CommandManager.GetNamedUIElement(_ownerInstanceName); return CommandManager.GetNamedUIElementCollection(_ownerInstanceName);
} }
return null; return null;
@ -256,13 +251,18 @@ namespace ICSharpCode.Core.Presentation
public ICollection<Type> OwnerTypes { public ICollection<Type> OwnerTypes {
get { get {
if(_ownerTypeName != null) { if(_ownerTypeName != null) {
return CommandManager.GetNamedUIType(_ownerTypeName); return CommandManager.GetNamedUITypeCollection(_ownerTypeName);
} }
return null; return null;
} }
} }
public bool IsRegistered
{
get; set;
}
private BindingsUpdatedHandler defaultCommandBindingHandler; private BindingsUpdatedHandler defaultCommandBindingHandler;
/// <summary> /// <summary>
@ -273,7 +273,7 @@ namespace ICSharpCode.Core.Presentation
get { get {
if(defaultCommandBindingHandler == null && OwnerTypeName != null) { if(defaultCommandBindingHandler == null && OwnerTypeName != null) {
defaultCommandBindingHandler = delegate { defaultCommandBindingHandler = delegate {
if(OwnerTypes != null && IsModifyed) { if(RoutedCommand != null && OwnerTypes != null && IsRegistered) {
GenerateCommandBindings(); GenerateCommandBindings();
foreach(var ownerType in OwnerTypes) { foreach(var ownerType in OwnerTypes) {
@ -285,13 +285,11 @@ namespace ICSharpCode.Core.Presentation
System.Windows.Input.CommandManager.RegisterClassCommandBinding(ownerType, binding); System.Windows.Input.CommandManager.RegisterClassCommandBinding(ownerType, binding);
} }
} }
IsModifyed = false;
} }
}; };
} else if(defaultCommandBindingHandler == null && OwnerInstanceName != null) { } else if(defaultCommandBindingHandler == null && OwnerInstanceName != null) {
defaultCommandBindingHandler = delegate { defaultCommandBindingHandler = delegate {
if(OwnerInstances != null && IsModifyed) { if(RoutedCommand != null && OwnerInstances != null && IsRegistered) {
GenerateCommandBindings(); GenerateCommandBindings();
foreach(var ownerInstance in OwnerInstances) { foreach(var ownerInstance in OwnerInstances) {
@ -301,8 +299,6 @@ namespace ICSharpCode.Core.Presentation
ownerInstance.CommandBindings.AddRange(ActiveCommandBindings); ownerInstance.CommandBindings.AddRange(ActiveCommandBindings);
} }
IsModifyed = false;
} }
}; };
} }
@ -323,14 +319,6 @@ namespace ICSharpCode.Core.Presentation
get; set; get; set;
} }
/// <summary>
/// Indicates whether <see cref="CommandBindingInfo" /> was modified. When modified
/// <see cref="CommandBinding" />s are re-generated
/// </summary>
public bool IsModifyed {
get; set;
}
/// <summary> /// <summary>
/// Re-generate <see cref="CommandBinding" /> from <see cref="CommandBindingInfo" /> /// Re-generate <see cref="CommandBinding" /> from <see cref="CommandBindingInfo" />
/// </summary> /// </summary>
@ -340,7 +328,7 @@ namespace ICSharpCode.Core.Presentation
ActiveCommandBindings = new CommandBindingCollection(); ActiveCommandBindings = new CommandBindingCollection();
if(IsActive) { if(BindingGroup.IsActive(this)) {
var commandBinding = new CommandBinding(RoutedCommand); var commandBinding = new CommandBinding(RoutedCommand);
commandBinding.CanExecute += GenerateCanExecuteEventHandler; commandBinding.CanExecute += GenerateCanExecuteEventHandler;
commandBinding.Executed += GenerateExecutedEventHandler; commandBinding.Executed += GenerateExecutedEventHandler;

361
src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandManager.cs

@ -30,24 +30,24 @@ namespace ICSharpCode.Core.Presentation
} }
// Binding infos // Binding infos
private static List<CommandBindingInfo> commandBindings = new List<CommandBindingInfo>(); private static HashSet<IBindingInfo> commandBindings = new HashSet<IBindingInfo>();
private static List<InputBindingInfo> inputBidnings = new List<InputBindingInfo>(); private static HashSet<IBindingInfo> inputBidnings = new HashSet<IBindingInfo>();
// Commands // Commands
private static Dictionary<string, RoutedUICommand> routedCommands = new Dictionary<string, RoutedUICommand>(); private static Dictionary<string, RoutedUICommand> routedCommands = new Dictionary<string, RoutedUICommand>();
internal static Dictionary<string, System.Windows.Input.ICommand> commands = new Dictionary<string, System.Windows.Input.ICommand>(); internal static Dictionary<string, System.Windows.Input.ICommand> commands = new Dictionary<string, System.Windows.Input.ICommand>();
// Command binding update hanlers // Binding update handlers
private static Dictionary<string, List<BindingsUpdatedHandler>> classCommandBindingUpdateHandlers = new Dictionary<string, List<BindingsUpdatedHandler>>(); private static Dictionary<IBindingInfo, HashSet<BindingsUpdatedHandler>> inputBindingUpdatedHandlers = new Dictionary<IBindingInfo, HashSet<BindingsUpdatedHandler>>();
private static Dictionary<string, List<BindingsUpdatedHandler>> instanceCommandBindingUpdateHandlers = new Dictionary<string, List<BindingsUpdatedHandler>>(); private static Dictionary<IBindingInfo, HashSet<BindingsUpdatedHandler>> commandBindingUpdatedHandlers = new Dictionary<IBindingInfo, HashSet<BindingsUpdatedHandler>>();
// Input binding update handlers
private static Dictionary<string, List<BindingsUpdatedHandler>> classInputBindingUpdateHandlers = new Dictionary<string, List<BindingsUpdatedHandler>>();
private static Dictionary<string, List<BindingsUpdatedHandler>> instanceInputBindingUpdateHandlers = new Dictionary<string, List<BindingsUpdatedHandler>>();
// Named instances and types // Named instances and types
private static Dictionary<string, List<UIElement>> namedUIInstances = new Dictionary<string, List<UIElement>>(); private static Dictionary<string, HashSet<UIElement>> namedUIInstances = new Dictionary<string, HashSet<UIElement>>();
private static Dictionary<string, List<Type>> namedUITypes = new Dictionary<string, List<Type>>(); private static Dictionary<string, HashSet<Type>> namedUITypes = new Dictionary<string, HashSet<Type>>();
// Reverse named instances and types (used to search for instance name by type)
private static Dictionary<UIElement, HashSet<string>> reverseNamedUIInstances = new Dictionary<UIElement, HashSet<string>>();
private static Dictionary<Type, HashSet<string>> reverseNamedUITypes = new Dictionary<Type, HashSet<string>>();
// Categories // Categories
public static List<InputBindingCategory> InputBindingCategories = new List<InputBindingCategory>(); public static List<InputBindingCategory> InputBindingCategories = new List<InputBindingCategory>();
@ -60,23 +60,19 @@ namespace ICSharpCode.Core.Presentation
public static void RegisterNamedUIElement(string instanceName, UIElement element) public static void RegisterNamedUIElement(string instanceName, UIElement element)
{ {
if(!namedUIInstances.ContainsKey(instanceName)){ if(!namedUIInstances.ContainsKey(instanceName)){
namedUIInstances.Add(instanceName, new List<UIElement>()); namedUIInstances.Add(instanceName, new HashSet<UIElement>());
} }
var namedUIInstanceCollection = namedUIInstances[instanceName]; if(!reverseNamedUIInstances.ContainsKey(element)) {
reverseNamedUIInstances.Add(element, new HashSet<string>());
if(!namedUIInstanceCollection.Contains(element)) { }
namedUIInstanceCollection.Add(element);
if(namedUIInstances[instanceName].Add(element)) {
reverseNamedUIInstances[element].Add(instanceName);
// If there are some bindings and update handlers already registered, // If there are some bindings and update handlers already registered,
// but owner is not loaded then invoke those bindings // but owner is not loaded then invoke those bindings
if(instanceCommandBindingUpdateHandlers.ContainsKey(instanceName)) { InvokeCommandBindingUpdateHandlers(new BindingInfoTemplate { OwnerInstanceName = instanceName });
InvokeCommandBindingUpdateHandlers(null, instanceName); InvokeInputBindingUpdateHandlers(new BindingInfoTemplate { OwnerInstanceName = instanceName });
}
if(instanceInputBindingUpdateHandlers.ContainsKey(instanceName)) {
InvokeInputBindingUpdateHandlers(null, instanceName);
}
} }
} }
@ -85,12 +81,20 @@ namespace ICSharpCode.Core.Presentation
/// </summary> /// </summary>
/// <param name="instanceName">Instance name</param> /// <param name="instanceName">Instance name</param>
/// <returns></returns> /// <returns></returns>
public static ICollection<UIElement> GetNamedUIElement(string instanceName) public static ICollection<UIElement> GetNamedUIElementCollection(string instanceName)
{ {
List<UIElement> instance; HashSet<UIElement> instances;
namedUIInstances.TryGetValue(instanceName, out instance); namedUIInstances.TryGetValue(instanceName, out instances);
return instance; return instances ?? new HashSet<UIElement>();
}
public static ICollection<string> GetUIElementNameCollection(UIElement instance)
{
HashSet<string> names;
reverseNamedUIInstances.TryGetValue(instance, out names);
return names ?? new HashSet<string>();
} }
/// <summary> /// <summary>
@ -101,22 +105,20 @@ namespace ICSharpCode.Core.Presentation
public static void RegisterNamedUIType(string typeName, Type type) public static void RegisterNamedUIType(string typeName, Type type)
{ {
if(!namedUITypes.ContainsKey(typeName)){ if(!namedUITypes.ContainsKey(typeName)){
namedUITypes.Add(typeName, new List<Type>()); namedUITypes.Add(typeName, new HashSet<Type>());
}
if(!reverseNamedUITypes.ContainsKey(type)) {
reverseNamedUITypes.Add(type, new HashSet<string>());
} }
var namedUITypeCollection = namedUITypes[typeName]; if(namedUITypes[typeName].Add(type)) {
if(!namedUITypeCollection.Contains(type)) { reverseNamedUITypes[type].Add(typeName);
namedUITypeCollection.Add(type);
// If any update handlers where assigned to the type and type was not // If any update handlers where assigned to the type and type was not
// loaded yet then invoke update handlers // loaded yet then invoke update handlers
if(classCommandBindingUpdateHandlers.ContainsKey(typeName)) { InvokeCommandBindingUpdateHandlers(new BindingInfoTemplate { OwnerTypeName = typeName });
InvokeCommandBindingUpdateHandlers(typeName, null); InvokeInputBindingUpdateHandlers(new BindingInfoTemplate { OwnerTypeName = typeName });
}
if(classInputBindingUpdateHandlers.ContainsKey(typeName)) {
InvokeInputBindingUpdateHandlers(typeName, null);
}
} }
} }
@ -125,12 +127,20 @@ namespace ICSharpCode.Core.Presentation
/// </summary> /// </summary>
/// <param name="typeName">Type name</param> /// <param name="typeName">Type name</param>
/// <returns>Type</returns> /// <returns>Type</returns>
public static List<Type> GetNamedUIType(string typeName) public static ICollection<Type> GetNamedUITypeCollection(string typeName)
{ {
List<Type> instance; HashSet<Type> instance;
namedUITypes.TryGetValue(typeName, out instance); namedUITypes.TryGetValue(typeName, out instance);
return instance; return instance ?? new HashSet<Type>();
}
public static ICollection<string> GetUITypeNameCollection(Type type)
{
HashSet<string> typeNames;
reverseNamedUITypes.TryGetValue(type, out typeNames);
return typeNames ?? new HashSet<string>();
} }
/// <summary> /// <summary>
@ -210,28 +220,37 @@ namespace ICSharpCode.Core.Presentation
/// <param name="inputBindingInfo">Input binding parameters</param> /// <param name="inputBindingInfo">Input binding parameters</param>
public static void RegisterInputBinding(InputBindingInfo inputBindingInfo) public static void RegisterInputBinding(InputBindingInfo inputBindingInfo)
{ {
var similarInputBinding = FindInputBindingInfos(inputBindingInfo.OwnerTypeName, inputBindingInfo.OwnerInstanceName, inputBindingInfo.RoutedCommandName, null).FirstOrDefault(); var similarBindingTemplate = new BindingInfoTemplate();
similarBindingTemplate.OwnerTypeName = inputBindingInfo.OwnerTypeName;
similarBindingTemplate.OwnerInstanceName = inputBindingInfo.OwnerInstanceName;
similarBindingTemplate.RoutedCommandName = inputBindingInfo.RoutedCommandName;
var similarInputBinding = FindInputBindingInfos(similarBindingTemplate).FirstOrDefault();
if(similarInputBinding != null) { if(similarInputBinding != null) {
foreach(InputGesture gesture in inputBindingInfo.DefaultGestures) { foreach(InputGesture gesture in inputBindingInfo.DefaultGestures) {
if(!similarInputBinding.DefaultGestures.ContainsTemplateFor(gesture, GestureCompareMode.ExactlyMatches)) { var existingGesture = new InputGestureCollection(similarInputBinding.DefaultGestures.ToList());
if(!existingGesture.ContainsTemplateFor(gesture, GestureCompareMode.ExactlyMatches)) {
similarInputBinding.DefaultGestures.Add(gesture); similarInputBinding.DefaultGestures.Add(gesture);
} }
} }
similarInputBinding.Categories.AddRange(inputBindingInfo.Categories); similarInputBinding.Categories.AddRange(inputBindingInfo.Categories);
similarInputBinding.Groups.AddRange(inputBindingInfo.Groups); similarInputBinding.Groups.AddRange(inputBindingInfo.Groups);
similarInputBinding.IsModifyed = true;
similarInputBinding.DefaultInputBindingHandler.Invoke();
} else { } else {
if(inputBindingInfo.OwnerInstanceName != null || inputBindingInfo.OwnerTypeName != null) { if(inputBindingInfo.OwnerInstanceName == null && inputBindingInfo.OwnerTypeName == null) {
RegisterDefaultInputBindingHandler(inputBindingInfo);
} else {
throw new ArgumentException("Binding owner must be specified"); throw new ArgumentException("Binding owner must be specified");
} }
var registeredBindingTemplate = new BindingInfoTemplate();
registeredBindingTemplate.OwnerInstanceName = inputBindingInfo.OwnerInstanceName;
registeredBindingTemplate.OwnerTypeName = inputBindingInfo.OwnerTypeName;
registeredBindingTemplate.RoutedCommandName = inputBindingInfo.RoutedCommandName;
inputBidnings.Add(inputBindingInfo); inputBidnings.Add(inputBindingInfo);
inputBindingInfo.IsRegistered = true;
RegisterInputBindingsUpdateHandler(registeredBindingTemplate, inputBindingInfo.DefaultInputBindingHandler);
InvokeInputBindingUpdateHandlers(registeredBindingTemplate);
} }
} }
@ -239,9 +258,9 @@ namespace ICSharpCode.Core.Presentation
/// Unregister input binding /// Unregister input binding
/// </summary> /// </summary>
/// <param name="inputBindingInfo">Input binding parameters</param> /// <param name="inputBindingInfo">Input binding parameters</param>
public static void UnregisterInputBinding(InputBindingInfo inputBindingInfo) public static void UnregisterInputBinding(BindingInfoTemplate template)
{ {
var similarInputBindingInfos = FindInputBindingInfos(inputBindingInfo.OwnerTypeName, inputBindingInfo.OwnerInstanceName, inputBindingInfo.RoutedCommandName, null); var similarInputBindingInfos = FindInputBindingInfos(template);
foreach(var similarInputBindingInfo in similarInputBindingInfos) { foreach(var similarInputBindingInfo in similarInputBindingInfos) {
inputBidnings.Remove(similarInputBindingInfo); inputBidnings.Remove(similarInputBindingInfo);
@ -271,39 +290,26 @@ namespace ICSharpCode.Core.Presentation
} }
} }
/// <summary> public static IEnumerable<InputBindingInfo> FindInputBindingInfos(params BindingInfoTemplate[] templates)
/// Find input input binding infos which satisfy provided arguments
///
/// Null arguments are ignored
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Unregister binding assigned to specific context instance</param>
/// <param name="routedCommandName">Routed UI command name</param>
public static ICollection<InputBindingInfo> FindInputBindingInfos(string ownerTypeName, string ownerInstanceName, string routedCommandName, BindingGroupCollection bindingGroups)
{ {
var foundBindings = new List<InputBindingInfo>(); return FindBindingInfos(inputBidnings, templates).Cast<InputBindingInfo>();
}
foreach(var binding in inputBidnings) {
if(binding.RoutedCommandName == "AvalonEditCommands.ConvertToUppercase")
{
}
if( (ownerInstanceName == null || binding.OwnerInstanceName == ownerInstanceName) private static IEnumerable<IBindingInfo> FindBindingInfos(ICollection<IBindingInfo> bindingInfos, params BindingInfoTemplate[] templates)
&& (ownerTypeName == null || binding.OwnerTypeName == ownerTypeName) {
&& (routedCommandName == null || binding.RoutedCommandName == routedCommandName) foreach(var binding in bindingInfos) {
&& (bindingGroups == null || bindingGroups.ContainsAnyFromCollection(binding.Groups)) foreach(var template in templates) {
) { if(template.IsTemplateFor(binding)) {
foundBindings.Add(binding); yield return binding;
continue;
}
} }
} }
return foundBindings;
} }
public static InputBindingCollection FindInputBindings(string ownerTypeName, string ownerInstanceName, string routedCommandName, BindingGroupCollection bindingGroups) public static InputBindingCollection FindInputBindings(params BindingInfoTemplate[] templates)
{ {
var inputBindingInfoCollection = FindInputBindingInfos(ownerTypeName, ownerInstanceName, routedCommandName, bindingGroups); var inputBindingInfoCollection = FindInputBindingInfos(templates);
var inputBindingCollection = new InputBindingCollection(); var inputBindingCollection = new InputBindingCollection();
foreach(var bindingInfo in inputBindingInfoCollection) { foreach(var bindingInfo in inputBindingInfoCollection) {
@ -369,15 +375,20 @@ namespace ICSharpCode.Core.Presentation
/// </summary> /// </summary>
/// <param name="commandBindingInfo">Command binding parameters</param> /// <param name="commandBindingInfo">Command binding parameters</param>
public static void RegisterCommandBinding(CommandBindingInfo commandBindingInfo) { public static void RegisterCommandBinding(CommandBindingInfo commandBindingInfo) {
commandBindingInfo.GenerateCommandBindings(); if(commandBindingInfo.OwnerInstanceName == null && commandBindingInfo.OwnerTypeName == null) {
if(commandBindingInfo.OwnerInstanceName != null || commandBindingInfo.OwnerTypeName != null) {
RegisterDefaultCommandBindingHandler(commandBindingInfo);
} else {
throw new ArgumentException("Binding owner must be specified"); throw new ArgumentException("Binding owner must be specified");
} }
var registeredBindingTemplate = new BindingInfoTemplate();
registeredBindingTemplate.OwnerInstanceName = commandBindingInfo.OwnerInstanceName;
registeredBindingTemplate.OwnerTypeName = commandBindingInfo.OwnerTypeName;
registeredBindingTemplate.RoutedCommandName = commandBindingInfo.RoutedCommandName;
commandBindings.Add(commandBindingInfo); commandBindings.Add(commandBindingInfo);
commandBindingInfo.IsRegistered = true;
RegisterInputBindingsUpdateHandler(registeredBindingTemplate, commandBindingInfo.DefaultCommandBindingHandler);
InvokeInputBindingUpdateHandlers(registeredBindingTemplate);
} }
/// <summary> /// <summary>
@ -385,7 +396,11 @@ namespace ICSharpCode.Core.Presentation
/// </summary> /// </summary>
/// <param name="commandBindingInfo">Command binding parameters</param> /// <param name="commandBindingInfo">Command binding parameters</param>
public static void UnregisterCommandBinding(CommandBindingInfo commandBindingInfo) { public static void UnregisterCommandBinding(CommandBindingInfo commandBindingInfo) {
var similarCommandBindingInfos = FindCommandBindingInfos(commandBindingInfo.OwnerTypeName, commandBindingInfo.OwnerInstanceName, commandBindingInfo.RoutedCommandName, null); var template = new BindingInfoTemplate();
template.OwnerTypeName = commandBindingInfo.OwnerTypeName;
template.OwnerInstanceName = commandBindingInfo.OwnerInstanceName;
template.RoutedCommandName = commandBindingInfo.RoutedCommandName;
var similarCommandBindingInfos = FindCommandBindingInfos(template);
foreach(var similarCommandBindingInfo in similarCommandBindingInfos) { foreach(var similarCommandBindingInfo in similarCommandBindingInfos) {
commandBindings.Remove(similarCommandBindingInfo); commandBindings.Remove(similarCommandBindingInfo);
@ -415,130 +430,64 @@ namespace ICSharpCode.Core.Presentation
} }
} }
#region Register bindings update handler #region Update handlers
/// <summary> private static void RegisterBindingsUpdateHandler(Dictionary<IBindingInfo, HashSet<BindingsUpdatedHandler>> bindingUpdateHandlersDictionary, IBindingInfo template, BindingsUpdatedHandler handler)
/// Register command binding update handler which is triggered when input bindings associated
/// with specified type change
/// </summary>
/// <param name="ownerTypeName">Owner type name</param>
/// <param name="handler">Update handler</param>
public static void RegisterClassCommandBindingsUpdateHandler(string ownerTypeName, BindingsUpdatedHandler handler)
{ {
if(!classCommandBindingUpdateHandlers.ContainsKey(ownerTypeName)) { if(!bindingUpdateHandlersDictionary.ContainsKey(template)) {
classCommandBindingUpdateHandlers.Add(ownerTypeName, new List<BindingsUpdatedHandler>()); bindingUpdateHandlersDictionary.Add(template, new HashSet<BindingsUpdatedHandler>());
} }
if(!classCommandBindingUpdateHandlers[ownerTypeName].Contains(handler)) { bindingUpdateHandlersDictionary[template].Add(handler);
classCommandBindingUpdateHandlers[ownerTypeName].Add(handler);
}
} }
/// <summary> /// <summary>
/// Register command binding update handler which is triggered when input bindings associated /// Register command binding update handler which is triggered when input bindings associated
/// with specified instance change
/// </summary>
/// <param name="instanceName">Owner instance name</param>
/// <param name="handler">Update handler</param>
public static void RegisterInstanceCommandBindingsUpdateHandler(string instanceName, BindingsUpdatedHandler handler)
{
if(!instanceCommandBindingUpdateHandlers.ContainsKey(instanceName)) {
instanceCommandBindingUpdateHandlers.Add(instanceName, new List<BindingsUpdatedHandler>());
}
instanceCommandBindingUpdateHandlers[instanceName].Add(handler);
}
/// <summary>
/// Register input binding update handler which is triggered when input bindings associated
/// with specified type change /// with specified type change
/// </summary> /// </summary>
/// <param name="ownerTypeName">Owner type name</param> /// <param name="ownerTypeName">Owner type name</param>
/// <param name="handler">Update handler</param> /// <param name="handler">Update handler</param>
public static void RegisterClassInputBindingsUpdateHandler(string ownerTypeName, BindingsUpdatedHandler handler) public static void RegisterCommandBindingsUpdateHandler(IBindingInfo template, BindingsUpdatedHandler handler)
{ {
if(!classInputBindingUpdateHandlers.ContainsKey(ownerTypeName)) { RegisterBindingsUpdateHandler(commandBindingUpdatedHandlers, template, handler);
classInputBindingUpdateHandlers.Add(ownerTypeName, new List<BindingsUpdatedHandler>());
}
if(!classInputBindingUpdateHandlers[ownerTypeName].Contains(handler)) {
classInputBindingUpdateHandlers[ownerTypeName].Add(handler);
}
} }
/// <summary> /// <summary>
/// Register input binding update handler which is triggered when input bindings associated /// Register command binding update handler which is triggered when input bindings associated
/// with specified instance change /// with specified type change
/// </summary> /// </summary>
/// <param name="instanceName">Owner instance name</param> /// <param name="ownerTypeName">Owner type name</param>
/// <param name="handler">Update handler</param> /// <param name="handler">Update handler</param>
public static void RegisterInstanceInputBindingsUpdateHandler(string instanceName, BindingsUpdatedHandler handler) public static void RegisterInputBindingsUpdateHandler(IBindingInfo template, BindingsUpdatedHandler handler)
{
if(!instanceInputBindingUpdateHandlers.ContainsKey(instanceName)) {
instanceInputBindingUpdateHandlers.Add(instanceName, new List<BindingsUpdatedHandler>());
}
instanceInputBindingUpdateHandlers[instanceName].Add(handler);
}
#endregion
#region Invoke binding update handlers
private static void InvokeBindingUpdateHandlers(Dictionary<string, List<BindingsUpdatedHandler>> updateHandlerDictionary, string ownertName)
{ {
if(ownertName != null && updateHandlerDictionary[ownertName] != null) { RegisterBindingsUpdateHandler(inputBindingUpdatedHandlers, template, handler);
foreach(var handler in updateHandlerDictionary[ownertName]) {
if(handler != null) {
handler.Invoke();
}
}
}
} }
private static void InvokeAllBindingUpdateHandlers(System.Collections.IDictionary updateHandlers) private static void InvokeBindingUpdateHandlers(Dictionary<IBindingInfo, HashSet<BindingsUpdatedHandler>> updateHandlerDictionary, params BindingInfoTemplate[] templates)
{ {
foreach(DictionaryEntry updateHandlerPair in updateHandlers) { foreach(var updateHandlerPair in updateHandlerDictionary) {
var handlers = (List<BindingsUpdatedHandler>)updateHandlerPair.Value; foreach(var template in templates) {
if(template.IsTemplateFor(updateHandlerPair.Key)) {
if(handlers != null) { foreach(var handler in updateHandlerPair.Value) {
foreach(var handler in handlers) { if(handler != null) {
if(handler != null) { handler.Invoke();
handler.Invoke(); }
} }
} }
} }
} }
} }
public static void InvokeCommandBindingUpdateHandlers() { public static void InvokeCommandBindingUpdateHandlers(params BindingInfoTemplate[] templates)
InvokeAllBindingUpdateHandlers(classCommandBindingUpdateHandlers);
InvokeAllBindingUpdateHandlers(instanceCommandBindingUpdateHandlers);
}
public static void InvokeInputBindingUpdateHandlers() {
InvokeAllBindingUpdateHandlers(classInputBindingUpdateHandlers);
InvokeAllBindingUpdateHandlers(instanceInputBindingUpdateHandlers);
}
/// <summary>
/// Invoke all inbut binding update handlers
/// </summary>
public static void InvokeInputBindingUpdateHandlers(string ownertTypeName, string ownerInstanceName)
{ {
InvokeBindingUpdateHandlers(classInputBindingUpdateHandlers, ownertTypeName); InvokeBindingUpdateHandlers(commandBindingUpdatedHandlers, templates);
InvokeBindingUpdateHandlers(instanceInputBindingUpdateHandlers, ownerInstanceName);
} }
/// <summary> public static void InvokeInputBindingUpdateHandlers(params BindingInfoTemplate[] templates)
/// Invoke all command binding update handlers
/// </summary>
public static void InvokeCommandBindingUpdateHandlers(string ownertTypeName, string ownerInstanceName)
{ {
InvokeBindingUpdateHandlers(classCommandBindingUpdateHandlers, ownertTypeName); InvokeBindingUpdateHandlers(inputBindingUpdatedHandlers, templates);
InvokeBindingUpdateHandlers(instanceCommandBindingUpdateHandlers, ownerInstanceName);
} }
#endregion #endregion
/// <summary> /// <summary>
@ -546,7 +495,7 @@ namespace ICSharpCode.Core.Presentation
/// </summary> /// </summary>
/// <param name="addIn">Add-in</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(CommandBindingInfo binding in commandBindings) {
if(binding.AddIn != addIn) continue; if(binding.AddIn != addIn) continue;
if(binding.CommandTypeName != null && !commands.ContainsKey(binding.CommandTypeName)){ if(binding.CommandTypeName != null && !commands.ContainsKey(binding.CommandTypeName)){
@ -588,26 +537,14 @@ namespace ICSharpCode.Core.Presentation
/// <param name="routedCommandName">Context class full name</param> /// <param name="routedCommandName">Context class full name</param>
/// <param name="className">Context class full name</param> /// <param name="className">Context class full name</param>
/// <returns>Collection of managed command bindings</returns> /// <returns>Collection of managed command bindings</returns>
public static ICollection<CommandBindingInfo> FindCommandBindingInfos(string ownerTypeName, string ownerInstanceName, string routedCommandName, BindingGroupCollection bindingGroups) public static IEnumerable<CommandBindingInfo> FindCommandBindingInfos(params BindingInfoTemplate[] templates)
{ {
var foundBindings = new List<CommandBindingInfo>(); return FindBindingInfos(commandBindings, templates).Cast<CommandBindingInfo>();
foreach(var binding in commandBindings) {
if( (ownerInstanceName == null || binding.OwnerInstanceName == ownerInstanceName)
&& (ownerTypeName == null || binding.OwnerTypeName == ownerTypeName)
&& (routedCommandName == null || binding.RoutedCommandName == routedCommandName)
&& (bindingGroups == null || bindingGroups.ContainsAnyFromCollection(binding.Groups))
) {
foundBindings.Add(binding);
}
}
return foundBindings;
} }
public static CommandBindingCollection FindCommandBindings(string ownerTypeName, string ownerInstanceName, string routedCommandName, BindingGroupCollection bindingGroups) public static CommandBindingCollection FindCommandBindings(params BindingInfoTemplate[] templates)
{ {
var commandBindingInfoCollection = FindCommandBindingInfos(ownerTypeName, ownerInstanceName, routedCommandName, bindingGroups); var commandBindingInfoCollection = FindCommandBindingInfos(templates);
var commandBindingCollection = new CommandBindingCollection(); var commandBindingCollection = new CommandBindingCollection();
foreach(var bindingInfo in commandBindingInfoCollection) { foreach(var bindingInfo in commandBindingInfoCollection) {
commandBindingCollection.AddRange(bindingInfo.ActiveCommandBindings); commandBindingCollection.AddRange(bindingInfo.ActiveCommandBindings);
@ -625,12 +562,12 @@ namespace ICSharpCode.Core.Presentation
/// <param name="contextInstance">Get gestures assigned only to specific context</param> /// <param name="contextInstance">Get gestures assigned only to specific context</param>
/// <param name="routedCommandName">Routed UI command name</param> /// <param name="routedCommandName">Routed UI command name</param>
/// <param name="gesture">Gesture</param> /// <param name="gesture">Gesture</param>
public static InputGestureCollection FindInputGestures(string ownerTypeName, string ownerInstanceName, string routedCommandName, BindingGroupCollection bindingGroups) { public static InputGestureCollection FindInputGestures(params BindingInfoTemplate[] templates) {
var bindings = FindInputBindingInfos(ownerTypeName, ownerInstanceName, routedCommandName, bindingGroups); var bindings = FindInputBindingInfos(templates);
var gestures = new InputGestureCollection(); var gestures = new InputGestureCollection();
foreach(InputBindingInfo bindingInfo in bindings) { foreach(InputBindingInfo bindingInfo in bindings) {
if(bindingInfo.ActiveGestures != null && bindingInfo.IsActive) { if(bindingInfo.ActiveGestures != null) {
foreach(InputGesture gesture in bindingInfo.ActiveGestures) { foreach(InputGesture gesture in bindingInfo.ActiveGestures) {
if(!gestures.ContainsTemplateFor(gesture, GestureCompareMode.ExactlyMatches)) { if(!gestures.ContainsTemplateFor(gesture, GestureCompareMode.ExactlyMatches)) {
gestures.Add(gesture); gestures.Add(gesture);
@ -700,42 +637,6 @@ namespace ICSharpCode.Core.Presentation
InputBindingCategories.Add(category); InputBindingCategories.Add(category);
} }
/// <summary>
/// Register default command binding update hander which will keep instance or type command
/// bindings upated
/// </summary>
/// <param name="commandBindingInfo">Command binding info</param>
private static void RegisterDefaultCommandBindingHandler(CommandBindingInfo commandBindingInfo)
{
if(commandBindingInfo.DefaultCommandBindingHandler != null) {
commandBindingInfo.DefaultCommandBindingHandler.Invoke();
}
if(commandBindingInfo.OwnerInstanceName != null) {
RegisterInstanceCommandBindingsUpdateHandler(commandBindingInfo.OwnerInstanceName, commandBindingInfo.DefaultCommandBindingHandler);
} else if(commandBindingInfo.OwnerTypeName != null) {
RegisterClassCommandBindingsUpdateHandler(commandBindingInfo.OwnerTypeName, commandBindingInfo.DefaultCommandBindingHandler);
}
}
/// <summary>
/// Register default input binding update hander which will keep instance or type command
/// bindings upated
/// </summary>
/// <param name="inputBindingInfo">Input binding info</param>
private static void RegisterDefaultInputBindingHandler(InputBindingInfo inputBindingInfo)
{
if(inputBindingInfo.DefaultInputBindingHandler != null) {
inputBindingInfo.DefaultInputBindingHandler.Invoke();
}
if(inputBindingInfo.OwnerInstanceName != null) {
RegisterInstanceInputBindingsUpdateHandler(inputBindingInfo.OwnerInstanceName, inputBindingInfo.DefaultInputBindingHandler);
} else if(inputBindingInfo.OwnerTypeName != null) {
RegisterClassInputBindingsUpdateHandler(inputBindingInfo.OwnerTypeName, inputBindingInfo.DefaultInputBindingHandler);
}
}
} }
public static class TypeExtensions public static class TypeExtensions

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

@ -200,7 +200,7 @@ namespace ICSharpCode.Core.Presentation
inputBindingInfo.AddIn = desc.Codon.AddIn; inputBindingInfo.AddIn = desc.Codon.AddIn;
inputBindingInfo.RoutedCommandName = desc.Command; inputBindingInfo.RoutedCommandName = desc.Command;
inputBindingInfo.DefaultGestures = gestures; inputBindingInfo.DefaultGestures.AddRange(gestures);
if(!string.IsNullOrEmpty(desc.CommandText)) { if(!string.IsNullOrEmpty(desc.CommandText)) {
inputBindingInfo.RoutedCommandText = desc.CommandText; inputBindingInfo.RoutedCommandText = desc.CommandText;
@ -234,7 +234,7 @@ namespace ICSharpCode.Core.Presentation
inputBindingInfo.AddIn = desc.Codon.AddIn; inputBindingInfo.AddIn = desc.Codon.AddIn;
inputBindingInfo.RoutedCommandName = desc.Command; inputBindingInfo.RoutedCommandName = desc.Command;
inputBindingInfo.DefaultGestures = gestures; inputBindingInfo.DefaultGestures.AddRange(gestures);
if(!string.IsNullOrEmpty(desc.CommandText)) { if(!string.IsNullOrEmpty(desc.CommandText)) {
inputBindingInfo.RoutedCommandText = desc.CommandText; inputBindingInfo.RoutedCommandText = desc.CommandText;

65
src/Main/ICSharpCode.Core.Presentation/CommandsService/IBindingInfo.cs

@ -0,0 +1,65 @@
/*
* Created by SharpDevelop.
* User: Sergej Andrejev
* Date: 7/17/2009
* Time: 10:55 AM
*/
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
public interface IBindingInfo
{
string OwnerInstanceName
{
get; set;
}
ICollection<UIElement> OwnerInstances
{
get;
}
string OwnerTypeName
{
get; set;
}
ICollection<Type> OwnerTypes
{
get;
}
string RoutedCommandName
{
get;
}
RoutedUICommand RoutedCommand
{
get;
}
BindingGroupCollection Groups
{
get;
}
}
public static class IBindingInfoExtensions
{
public static bool IsTemplateFor(this IBindingInfo template, IBindingInfo binding)
{
return (template.OwnerInstanceName == null || template.OwnerInstanceName == binding.OwnerInstanceName)
&& (template.OwnerInstances == null || (binding.OwnerInstances != null && template.OwnerInstances.ContainsAnyFromCollection(binding.OwnerInstances)))
&& (template.OwnerTypeName == null || template.OwnerTypeName == binding.OwnerTypeName)
&& (template.OwnerTypes == null || (binding.OwnerTypes != null && template.OwnerTypes.ContainsAnyFromCollection(binding.OwnerTypes)))
&& (template.RoutedCommandName == null || template.RoutedCommandName == binding.RoutedCommandName)
&& (template.RoutedCommand == null || template.RoutedCommand == binding.RoutedCommand);
}
}
}

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

@ -3,58 +3,33 @@ using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Collections.ObjectModel;
namespace ICSharpCode.Core.Presentation namespace ICSharpCode.Core.Presentation
{ {
/// <summary> /// <summary>
/// Stores details about input binding /// Stores details about input binding
/// </summary> /// </summary>
public class InputBindingInfo public class InputBindingInfo : IBindingInfo
{ {
/// <summary> /// <summary>
/// Creates new instance of <see cref="InputBindingInfo"/> /// Creates new instance of <see cref="InputBindingInfo"/>
/// </summary> /// </summary>
public InputBindingInfo() public InputBindingInfo()
{ {
IsModifyed = true;
OldInputBindings = new InputBindingCollection(); OldInputBindings = new InputBindingCollection();
ActiveInputBindings = new InputBindingCollection(); ActiveInputBindings = new InputBindingCollection();
DefaultGestures = new InputGestureCollection(); DefaultGestures = new ObservableInputGestureCollection();
Categories = new InputBindingCategoryCollection(); Categories = new InputBindingCategoryCollection();
Groups = new BindingGroupCollection(); Groups = new BindingGroupCollection();
Groups.CollectionChanged += Groups_CollectionChanged; Groups.CollectionChanged += Groups_CollectionChanged;
} }
private void Groups_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
if(e.OldItems != null) {
foreach(BindingGroup oldGroup in e.OldItems) {
oldGroup.InputBindings.Remove(this);
}
}
if(e.NewItems != null) {
foreach(BindingGroup oldGroup in e.NewItems) {
oldGroup.InputBindings.Add(this);
}
}
}
public BindingGroupCollection Groups public BindingGroupCollection Groups
{ {
get; private set; get; private set;
} }
public bool IsActive
{
get {
if(OwnerInstanceName != null && Groups != null && Groups.Count > 0) {
return Groups.IsAttachedTo(OwnerInstanceName);
}
return true;
}
}
public string _ownerInstanceName; public string _ownerInstanceName;
/// <summary> /// <summary>
@ -69,11 +44,15 @@ namespace ICSharpCode.Core.Presentation
return _ownerInstanceName; return _ownerInstanceName;
} }
set { set {
var backup = _ownerInstanceName;
if(_ownerInstanceName != null || _ownerTypeName != null) { if(_ownerInstanceName != null || _ownerTypeName != null) {
throw new ArgumentException("This binding already has an owner"); throw new ArgumentException("This binding already has an owner");
} }
_ownerInstanceName = value; _ownerInstanceName = value;
SetActiveGesturesChanged(RoutedCommandName, _ownerTypeName, OwnerTypeName);
} }
} }
@ -87,7 +66,7 @@ namespace ICSharpCode.Core.Presentation
public ICollection<UIElement> OwnerInstances { public ICollection<UIElement> OwnerInstances {
get { get {
if(_ownerInstanceName != null) { if(_ownerInstanceName != null) {
return CommandManager.GetNamedUIElement(_ownerInstanceName); return CommandManager.GetNamedUIElementCollection(_ownerInstanceName);
} }
return null; return null;
@ -103,16 +82,20 @@ namespace ICSharpCode.Core.Presentation
/// If this attribute is used <see cref="OwnerInstance" />, <see cref="OwnerInstanceName" /> and /// If this attribute is used <see cref="OwnerInstance" />, <see cref="OwnerInstanceName" /> and
/// <see cref="OwnerType" /> can not be set /// <see cref="OwnerType" /> can not be set
/// </summary> /// </summary>
public string OwnerTypeName{ public string OwnerTypeName
{
get { get {
return _ownerTypeName; return _ownerTypeName;
} }
set { set {
var backup = _ownerTypeName;
if(_ownerInstanceName != null || _ownerTypeName != null) { if(_ownerInstanceName != null || _ownerTypeName != null) {
throw new ArgumentException("This binding already has an owner"); throw new ArgumentException("This binding already has an owner");
} }
_ownerTypeName = value; _ownerTypeName = value;
SetActiveGesturesChanged(RoutedCommandName, OwnerInstanceName, _ownerTypeName);
} }
} }
@ -126,7 +109,7 @@ namespace ICSharpCode.Core.Presentation
public ICollection<Type> OwnerTypes { public ICollection<Type> OwnerTypes {
get { get {
if(_ownerTypeName != null) { if(_ownerTypeName != null) {
return CommandManager.GetNamedUIType(_ownerTypeName); return CommandManager.GetNamedUITypeCollection(_ownerTypeName);
} }
return null; return null;
@ -150,17 +133,38 @@ namespace ICSharpCode.Core.Presentation
get; set; get; set;
} }
private InputGestureCollection _defaultGestures; private ObservableInputGestureCollection _defaultGestures;
/// <summary> /// <summary>
/// Gestures which triggers this binding /// Gestures which triggers this binding
/// </summary> /// </summary>
public InputGestureCollection DefaultGestures { public ObservableInputGestureCollection DefaultGestures {
get { get {
return _defaultGestures; return _defaultGestures;
} }
set { set {
_defaultGestures = value; _defaultGestures = value;
if(value != null)
{
_defaultGestures.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e) {
// Check for active profile but no custom shortcut
if(UserDefinedGesturesManager.CurrentProfile == null) {
var innerArgs = new InputBindingGesturesChangedArgs();
innerArgs.InputBindingIdentifier = Identifier;
ActiveGesturesChanged(this, innerArgs);
}
};
}
if(routedCommandName != null && (_ownerInstanceName != null || _ownerTypeName != null)) {
var args = new InputBindingGesturesChangedArgs();
args.InputBindingIdentifier = Identifier;
if(UserDefinedGesturesManager.CurrentProfile == null) {
ActiveGesturesChanged(this, args);
}
}
} }
} }
@ -171,18 +175,27 @@ namespace ICSharpCode.Core.Presentation
get { get {
if(UserDefinedGesturesManager.CurrentProfile == null if(UserDefinedGesturesManager.CurrentProfile == null
|| UserDefinedGesturesManager.CurrentProfile[Identifier] == null) { || UserDefinedGesturesManager.CurrentProfile[Identifier] == null) {
return DefaultGestures; return DefaultGestures.GetInputGestureCollection();
} }
return UserDefinedGesturesManager.CurrentProfile[Identifier]; return UserDefinedGesturesManager.CurrentProfile[Identifier];
} }
} }
private string routedCommandName;
/// <summary> /// <summary>
/// Name of the routed command which will be invoked when this binding is triggered /// Name of the routed command which will be invoked when this binding is triggered
/// </summary> /// </summary>
public string RoutedCommandName { public string RoutedCommandName {
get; set; get {
return routedCommandName;
}
set {
var backup = routedCommandName;
routedCommandName = value;
SetActiveGesturesChanged(backup, OwnerInstanceName, OwnerTypeName);
}
} }
/// <summary> /// <summary>
@ -201,23 +214,67 @@ namespace ICSharpCode.Core.Presentation
get; private set; get; private set;
} }
public bool IsRegistered
{
get; set;
}
public event ActiveInputBindingsChangedHandler ActiveInputBindingsChanged;
/// <summary> /// <summary>
/// Indicates whether <see cref="InputBindingInfo" /> was modified. When modified /// New input bindings are assigned to owner when <see cref="CommandBindingInfo" /> is modified
/// <see cref="InputBinding" />s are re-generated
/// </summary> /// </summary>
public bool IsModifyed { public InputBindingCollection ActiveInputBindings
{
get; set; get; set;
} }
public InputBindingIdentifier Identifier {
get {
var identifier = new InputBindingIdentifier();
identifier.OwnerInstanceName = OwnerInstanceName;
identifier.OwnerTypeName = OwnerTypeName;
identifier.RoutedCommandName = RoutedCommandName;
return identifier;
}
}
private void Groups_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.OldItems != null) {
foreach(BindingGroup oldGroup in e.OldItems) {
oldGroup.InputBindings.Remove(this);
}
}
if(e.NewItems != null) {
foreach(BindingGroup oldGroup in e.NewItems) {
oldGroup.InputBindings.Add(this);
}
}
}
private void ActiveGesturesChanged(object sender, InputBindingGesturesChangedArgs args)
{
var template = new BindingInfoTemplate();
template.OwnerInstanceName = OwnerInstanceName;
template.OwnerTypeName = OwnerTypeName;
template.RoutedCommandName = RoutedCommandName;
CommandManager.InvokeInputBindingUpdateHandlers(template);
}
/// <summary> /// <summary>
/// Re-generate <see cref="InputBinding" /> from <see cref="InputBindingInfo" /> /// Re-generate <see cref="InputBinding" /> from <see cref="InputBindingInfo" />
/// </summary> /// </summary>
public void GenerateInputBindings() private void GenerateInputBindings()
{ {
OldInputBindings = ActiveInputBindings; OldInputBindings = ActiveInputBindings;
ActiveInputBindings = new InputBindingCollection(); ActiveInputBindings = new InputBindingCollection();
if(ActiveGestures != null && IsActive) { if(ActiveGestures != null && BindingGroup.IsActive(this)) {
foreach(InputGesture gesture in ActiveGestures) { foreach(InputGesture gesture in ActiveGestures) {
var inputBinding = new InputBinding(RoutedCommand, gesture); var inputBinding = new InputBinding(RoutedCommand, gesture);
ActiveInputBindings.Add(inputBinding); ActiveInputBindings.Add(inputBinding);
@ -236,7 +293,7 @@ namespace ICSharpCode.Core.Presentation
get { get {
if(defaultInputBindingHandler == null && OwnerTypeName != null) { if(defaultInputBindingHandler == null && OwnerTypeName != null) {
defaultInputBindingHandler = delegate { defaultInputBindingHandler = delegate {
if(OwnerTypes != null && IsModifyed) { if(RoutedCommand != null && OwnerTypes != null && IsRegistered) {
GenerateInputBindings(); GenerateInputBindings();
foreach(var ownerType in OwnerTypes) { foreach(var ownerType in OwnerTypes) {
@ -251,12 +308,14 @@ namespace ICSharpCode.Core.Presentation
CommandManager.OrderClassInputBindingsByChords(ownerType); CommandManager.OrderClassInputBindingsByChords(ownerType);
} }
IsModifyed = false; if(ActiveInputBindingsChanged != null) {
ActiveInputBindingsChanged.Invoke(this);
}
} }
}; };
} else if(defaultInputBindingHandler == null && OwnerInstanceName != null){ } else if(defaultInputBindingHandler == null && OwnerInstanceName != null){
defaultInputBindingHandler = delegate { defaultInputBindingHandler = delegate {
if(OwnerInstances != null && IsModifyed) { if(RoutedCommand != null && OwnerInstances != null && IsRegistered) {
GenerateInputBindings(); GenerateInputBindings();
foreach(var ownerInstance in OwnerInstances) { foreach(var ownerInstance in OwnerInstances) {
@ -268,8 +327,6 @@ namespace ICSharpCode.Core.Presentation
CommandManager.OrderInstanceInputBindingsByChords(ownerInstance); CommandManager.OrderInstanceInputBindingsByChords(ownerInstance);
} }
IsModifyed = false;
} }
}; };
} }
@ -289,22 +346,19 @@ namespace ICSharpCode.Core.Presentation
get; set; get; set;
} }
/// <summary> private void SetActiveGesturesChanged(string oldRoutedCommandName, string oldOwnerInstanceName, string oldOwnerTypeName)
/// New input bindings are assigned to owner when <see cref="CommandBindingInfo" /> is modified
/// </summary>
public InputBindingCollection ActiveInputBindings
{ {
get; set; if(oldRoutedCommandName != null && (oldOwnerInstanceName != null || oldOwnerTypeName != null)) {
} var oldIdentifier = new InputBindingIdentifier();
oldIdentifier.OwnerInstanceName = oldOwnerInstanceName;
oldIdentifier.OwnerTypeName = oldOwnerTypeName;
oldIdentifier.RoutedCommandName = oldRoutedCommandName;
public InputBindingIdentifier Identifier { UserDefinedGesturesManager.RemoveActiveGesturesChangedHandler(oldIdentifier, ActiveGesturesChanged);
get { }
var identifier = new InputBindingIdentifier();
identifier.OwnerInstanceName = OwnerInstanceName;
identifier.OwnerTypeName = OwnerTypeName;
identifier.RoutedCommandName = RoutedCommandName;
return identifier; if(RoutedCommandName != null && (OwnerInstanceName != null || OwnerTypeName != null)) {
UserDefinedGesturesManager.AddActiveGesturesChangedHandler(Identifier, ActiveGesturesChanged);
} }
} }
} }
@ -324,4 +378,6 @@ namespace ICSharpCode.Core.Presentation
get; set; get; set;
} }
} }
public delegate void ActiveInputBindingsChangedHandler(InputBindingInfo inputBindingInfo);
} }

131
src/Main/ICSharpCode.Core.Presentation/CommandsService/ObservableInputGestureCollection.cs

@ -0,0 +1,131 @@
/*
* Created by SharpDevelop.
* User: Sergej Andrejev
* Date: 7/17/2009
* Time: 8:56 AM
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Description of ObservableInputBindingCollection.
/// </summary>
public class ObservableInputGestureCollection : IList<InputGesture>, IEnumerable<InputGesture>, ICollection<InputGesture>
{
private ObservableCollection<InputGesture> observedInputGestures;
public ObservableInputGestureCollection()
{
observedInputGestures = new ObservableCollection<InputGesture>();
observedInputGestures.CollectionChanged += observedInputGestures_CollectionChanged;
}
public void Add(InputGesture item)
{
observedInputGestures.Add(item);
}
public void Insert(int index, InputGesture item)
{
observedInputGestures.Insert(index, item);
}
public void RemoveAt(int index)
{
observedInputGestures.RemoveAt(index);
}
public InputGesture this[int index]
{
get {
return observedInputGestures[index];
}
set {
observedInputGestures[index] = value;
}
}
public bool IsReadOnly
{
get {
return false;
}
}
public int Count
{
get {
return observedInputGestures.Count;
}
}
public bool Remove(InputGesture item)
{
return observedInputGestures.Remove(item);
}
public void Clear()
{
observedInputGestures.Clear();
}
public bool Contains(InputGesture item)
{
return observedInputGestures.Contains(item);
}
public InputGestureCollection GetInputGestureCollection()
{
return new InputGestureCollection(observedInputGestures);
}
public void AddRange(InputGestureCollection items)
{
foreach(InputGesture item in items) {
Add(item);
}
}
public void AddRange(IEnumerable<InputGesture> items)
{
foreach(InputGesture item in items) {
Add(item);
}
}
public void CopyTo(InputGesture[] array, int arrayIndex)
{
observedInputGestures.CopyTo(array, arrayIndex);
}
public IEnumerator<InputGesture> GetEnumerator()
{
return observedInputGestures.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return observedInputGestures.GetEnumerator();
}
public int IndexOf(InputGesture value)
{
return observedInputGestures.IndexOf(value);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
private void observedInputGestures_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(CollectionChanged != null) {
CollectionChanged.Invoke(sender, e);
}
}
}
}

81
src/Main/ICSharpCode.Core.Presentation/CommandsService/UserDefinedGesturesManager.cs

@ -21,6 +21,8 @@ namespace ICSharpCode.Core.Presentation
Directory.CreateDirectory(_userGestureProfilesDirectory); Directory.CreateDirectory(_userGestureProfilesDirectory);
} }
} }
CurrentProfileChanged += CurrentProfile_CurrentProfileChanged;
} }
/// <summary> /// <summary>
@ -36,6 +38,35 @@ namespace ICSharpCode.Core.Presentation
private static UserGesturesProfile _currentProfile; private static UserGesturesProfile _currentProfile;
private static bool _isCurrentProfileLoaded; private static bool _isCurrentProfileLoaded;
public static event UserGestureProfileChangedHandler CurrentProfileChanged;
private static Dictionary<InputBindingIdentifier, HashSet<InputBindingGesturesChangedHandler>> ActiveGesturesChangedHandlers = new Dictionary<InputBindingIdentifier, HashSet<InputBindingGesturesChangedHandler>>();
public static void AddActiveGesturesChangedHandler(InputBindingIdentifier identifier, InputBindingGesturesChangedHandler handler)
{
if(!ActiveGesturesChangedHandlers.ContainsKey(identifier)) {
ActiveGesturesChangedHandlers.Add(identifier, new HashSet<InputBindingGesturesChangedHandler>());
}
ActiveGesturesChangedHandlers[identifier].Add(handler);
}
public static void RemoveActiveGesturesChangedHandler(InputBindingIdentifier identifier, InputBindingGesturesChangedHandler handler)
{
if(ActiveGesturesChangedHandlers.ContainsKey(identifier)) {
ActiveGesturesChangedHandlers[identifier].Remove(handler);
}
}
private static void InvokeActiveGesturesChangedHandlers(InputBindingIdentifier identifier)
{
var args = new InputBindingGesturesChangedArgs { InputBindingIdentifier = identifier };
if(ActiveGesturesChangedHandlers.ContainsKey(identifier)) {
foreach(var handler in ActiveGesturesChangedHandlers[identifier]) {
handler.Invoke(typeof(UserDefinedGesturesManager), args);
}
}
}
public static UserGesturesProfile CurrentProfile public static UserGesturesProfile CurrentProfile
{ {
get { get {
@ -48,6 +79,12 @@ namespace ICSharpCode.Core.Presentation
profile.Load(); profile.Load();
_currentProfile = profile; _currentProfile = profile;
if(CurrentProfileChanged != null) {
var args = new UserGestureProfileChangedArgs();
args.NewProfile = profile;
CurrentProfileChanged.Invoke(typeof(UserDefinedGesturesManager), args);
}
} }
_isCurrentProfileLoaded = true; _isCurrentProfileLoaded = true;
@ -56,8 +93,16 @@ namespace ICSharpCode.Core.Presentation
return _currentProfile; return _currentProfile;
} }
set { set {
var currentProfileBackup = _currentProfile;
_currentProfile = value; _currentProfile = value;
if(_currentProfile != currentProfileBackup && CurrentProfileChanged != null) {
var args = new UserGestureProfileChangedArgs();
args.NewProfile = _currentProfile;
args.OldProfile = currentProfileBackup;
CurrentProfileChanged.Invoke(typeof(UserDefinedGesturesManager), args);
}
var currentProfilePath = value != null ? value.Path : null; var currentProfilePath = value != null ? value.Path : null;
if(currentProfilePath != null) { if(currentProfilePath != null) {
@ -69,5 +114,41 @@ namespace ICSharpCode.Core.Presentation
_isCurrentProfileLoaded = true; _isCurrentProfileLoaded = true;
} }
} }
private static void CurrentProfile_CurrentProfileChanged(object sender, UserGestureProfileChangedArgs args) {
var identifiers = new HashSet<InputBindingIdentifier>();
if(args.OldProfile != null) {
foreach(var gesture in args.OldProfile) {
identifiers.Add(gesture.Key);
}
}
if(args.NewProfile != null) {
foreach(var gesture in args.NewProfile) {
identifiers.Add(gesture.Key);
}
}
foreach(var identifier in identifiers) {
InvokeActiveGesturesChangedHandlers(identifier);
}
}
} }
public class UserGestureProfileChangedArgs
{
public UserGesturesProfile OldProfile
{
get; set;
}
public UserGesturesProfile NewProfile
{
get; set;
}
}
public delegate void UserGestureProfileChangedHandler(object sender, UserGestureProfileChangedArgs args);
} }

25
src/Main/ICSharpCode.Core.Presentation/CommandsService/UserGesturesProfile.cs

@ -10,10 +10,10 @@ using System;
using System.Xml; using System.Xml;
using System.Windows.Input; using System.Windows.Input;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace ICSharpCode.Core.Presentation namespace ICSharpCode.Core.Presentation
{ {
/// <summary> /// <summary>
/// Description of UserGesturesProfile. /// Description of UserGesturesProfile.
/// </summary> /// </summary>
@ -141,8 +141,17 @@ namespace ICSharpCode.Core.Presentation
xmlDocument.Save(Path); xmlDocument.Save(Path);
} }
public event InputBindingGesturesChangedHandler InputBindingGesturesChanged;
public void Clear() public void Clear()
{ {
if(InputBindingGesturesChanged != null) {
var identifiers = new List<InputBindingIdentifier>();
foreach(var userDefinedGesture in userDefinedGestures) {
InputBindingGesturesChanged.Invoke(this, new InputBindingGesturesChangedArgs { InputBindingIdentifier = userDefinedGesture.Key});
}
}
userDefinedGestures.Clear(); userDefinedGestures.Clear();
} }
@ -172,6 +181,10 @@ namespace ICSharpCode.Core.Presentation
/// <param name="inputGestureCollection">Gesture assigned to this input binding</param> /// <param name="inputGestureCollection">Gesture assigned to this input binding</param>
private void SetInputBindingGestures(InputBindingIdentifier identifier, InputGestureCollection inputGestureCollection) private void SetInputBindingGestures(InputBindingIdentifier identifier, InputGestureCollection inputGestureCollection)
{ {
if(InputBindingGesturesChanged != null) {
InputBindingGesturesChanged.Invoke(this, new InputBindingGesturesChangedArgs { InputBindingIdentifier = identifier});
}
userDefinedGestures[identifier] = inputGestureCollection; userDefinedGestures[identifier] = inputGestureCollection;
} }
@ -196,4 +209,14 @@ namespace ICSharpCode.Core.Presentation
return profile; return profile;
} }
} }
public class InputBindingGesturesChangedArgs
{
public InputBindingIdentifier InputBindingIdentifier
{
get; set;
}
}
public delegate void InputBindingGesturesChangedHandler(object sender, InputBindingGesturesChangedArgs args);
} }

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

@ -69,14 +69,17 @@
</Compile> </Compile>
<Compile Include="CommandsService\BindingGroup.cs" /> <Compile Include="CommandsService\BindingGroup.cs" />
<Compile Include="CommandsService\BindingGroupCollection.cs" /> <Compile Include="CommandsService\BindingGroupCollection.cs" />
<Compile Include="CommandsService\BindingInfoTemplate.cs" />
<Compile Include="CommandsService\BindingsUpdatedHandler.cs" /> <Compile Include="CommandsService\BindingsUpdatedHandler.cs" />
<Compile Include="CommandsService\CommandBindingInfo.cs" /> <Compile Include="CommandsService\CommandBindingInfo.cs" />
<Compile Include="CommandsService\CommandManager.cs" /> <Compile Include="CommandsService\CommandManager.cs" />
<Compile Include="CommandsService\CommandsService.cs" /> <Compile Include="CommandsService\CommandsService.cs" />
<Compile Include="CommandsService\GesturePlaceHolderRegistry.cs" /> <Compile Include="CommandsService\GesturePlaceHolderRegistry.cs" />
<Compile Include="CommandsService\IBindingInfo.cs" />
<Compile Include="CommandsService\InputBindingCategory.cs" /> <Compile Include="CommandsService\InputBindingCategory.cs" />
<Compile Include="CommandsService\InputBindingCategoryCollection.cs" /> <Compile Include="CommandsService\InputBindingCategoryCollection.cs" />
<Compile Include="CommandsService\InputBindingInfo.cs" /> <Compile Include="CommandsService\InputBindingInfo.cs" />
<Compile Include="CommandsService\ObservableInputGestureCollection.cs" />
<Compile Include="CommandsService\UserDefinedGesturesManager.cs" /> <Compile Include="CommandsService\UserDefinedGesturesManager.cs" />
<Compile Include="CommandsService\UserGesturesProfile.cs" /> <Compile Include="CommandsService\UserGesturesProfile.cs" />
<Compile Include="CommandsService\WpfCommandWrapper.cs" /> <Compile Include="CommandsService\WpfCommandWrapper.cs" />

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

@ -130,20 +130,27 @@ namespace ICSharpCode.Core.Presentation
var routedCommand = CommandManager.GetRoutedUICommand(routedCommandName); var routedCommand = CommandManager.GetRoutedUICommand(routedCommandName);
if(routedCommand != null) { if(routedCommand != null) {
this.Command = routedCommand; this.Command = routedCommand;
} else
{
Console.WriteLine(routedCommandName);
} }
// Register input bindings update handler // Register input bindings update handler
BindingsUpdatedHandler gesturesUpdateHandler = delegate { BindingsUpdatedHandler gesturesUpdateHandler = delegate {
var updatedGestures = CommandManager.FindInputGestures(null, null, routedCommandName, null); var gesturesTemplate = new BindingInfoTemplate();
gesturesTemplate.RoutedCommandName = routedCommandName;
var updatedGestures = CommandManager.FindInputGestures(gesturesTemplate);
this.InputGestureText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures); this.InputGestureText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures);
}; };
gesturesUpdateHandler.Invoke(); gesturesUpdateHandler.Invoke();
CommandManager.RegisterClassInputBindingsUpdateHandler(CommandManager.DefaultContextName, gesturesUpdateHandler);
var bindingTemplate = new BindingInfoTemplate();
if(codon.Properties.Contains("ownerinstance")) {
bindingTemplate.OwnerInstanceName = codon.Properties["ownerinstance"];
} else if(codon.Properties.Contains("ownertype")) {
bindingTemplate.OwnerTypeName = codon.Properties["ownertype"];
}
bindingTemplate.RoutedCommandName = routedCommandName;
CommandManager.RegisterInputBindingsUpdateHandler(bindingTemplate, gesturesUpdateHandler);
} }
} }
} }

Loading…
Cancel
Save