diff --git a/AddIns/ICSharpCode.SharpDevelop.addin b/AddIns/ICSharpCode.SharpDevelop.addin index dd7eec13d8..c1ea3018ba 100644 --- a/AddIns/ICSharpCode.SharpDevelop.addin +++ b/AddIns/ICSharpCode.SharpDevelop.addin @@ -130,7 +130,9 @@ command="SDBuildCommands.BuildSolution" class="ICSharpCode.SharpDevelop.Project.Commands.Build" gestures="F8" - category="Building" /> + category="Building" + owner-instance="ICSharpCode.SharpDevelop.Gui.ClassBrowser.ClassBrowserPad" + /> a.Name == "SharpDevelop")); - CommandsRegistry.RegisterCommandBindingsUpdateHandler(CommandsRegistry.DefaultContextName, null, delegate { - var newBindings = CommandsRegistry.FindCommandBindings(CommandsRegistry.DefaultContextName, null, null, null); - CommandsRegistry.RemoveManagedCommandBindings(CommandBindings); - CommandBindings.AddRange(newBindings); - }); + //CommandsRegistry.RegisterCommandBindingsUpdateHandler(CommandsRegistry.DefaultContextName, null, delegate { + // var newBindings = CommandsRegistry.FindCommandBindings(CommandsRegistry.DefaultContextName, null, null, null); + // CommandsRegistry.RemoveManagedCommandBindings(CommandBindings); + // CommandBindings.AddRange(newBindings); + //}); - CommandsRegistry.RegisterInputBindingUpdateHandler(CommandsRegistry.DefaultContextName, null, delegate { - var newBindings = CommandsRegistry.FindInputBindings(null, null, null); - CommandsRegistry.RemoveManagedInputBindings(InputBindings); - InputBindings.AddRange(newBindings); - }); - - CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContextName, null); - CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContextName, null); + //CommandsRegistry.RegisterInputBindingUpdateHandler(CommandsRegistry.DefaultContextName, null, delegate { + // var newBindings = CommandsRegistry.FindInputBindings(null, null, null); + // CommandsRegistry.RemoveManagedInputBindings(InputBindings); + // InputBindings.AddRange(newBindings); + //}); mainMenu.ItemsSource = MenuService.CreateMenuItems(this, this, mainMenuPath); diff --git a/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDescriptor.cs b/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDescriptor.cs index 856f33d900..28bc7ffb94 100644 --- a/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDescriptor.cs +++ b/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDescriptor.cs @@ -38,12 +38,11 @@ namespace ICSharpCode.Core get; private set; } - /// - /// Full name of context class. - /// - /// UI element in which this binding will be valid - /// - public string Context { + public string OwnerInstanceName { + get; private set; + } + + public string OwnerTypeName { get; private set; } @@ -86,7 +85,8 @@ namespace ICSharpCode.Core Class = Codon.Properties["class"]; Command = Codon.Properties["command"]; CommandText = Codon.Properties["commandtext"]; - Context = Codon.Properties["context"]; + OwnerInstanceName = Codon.Properties["owner-instance"]; + OwnerTypeName = Codon.Properties["owner-type"]; Gestures = Codon.Properties["gestures"]; Category = Codon.Properties["category"]; } diff --git a/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDescriptor.cs b/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDescriptor.cs index f3534ab70a..853278fc62 100644 --- a/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDescriptor.cs +++ b/src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDescriptor.cs @@ -28,12 +28,11 @@ namespace ICSharpCode.Core get; private set; } - /// - /// Full name of context class. - /// - /// UI element in which this binding will be valid - /// - public string Context { + public string OwnerInstanceName { + get; private set; + } + + public string OwnerTypeName { get; private set; } @@ -60,7 +59,8 @@ namespace ICSharpCode.Core Codon = codon; Command = codon.Properties["command"]; CommandText = codon.Properties["commandtext"]; - Context = codon.Properties["context"]; + OwnerInstanceName = codon.Properties["owner-instance"]; + OwnerTypeName = codon.Properties["owner-type"]; Gestures = codon.Properties["gestures"]; Category = codon.Properties["category"]; } diff --git a/src/Main/Core/Project/Src/AddInTree/AddIn/Runtime.cs b/src/Main/Core/Project/Src/AddInTree/AddIn/Runtime.cs index 0f4c5ddff6..182f1ae6b5 100644 --- a/src/Main/Core/Project/Src/AddInTree/AddIn/Runtime.cs +++ b/src/Main/Core/Project/Src/AddInTree/AddIn/Runtime.cs @@ -84,6 +84,10 @@ namespace ICSharpCode.Core // preload assembly to provoke FileLoadException if dependencies are missing loadedAssembly.GetExportedTypes(); #endif + + if(Loaded != null) { + Loaded(this, null); + } } catch (FileNotFoundException ex) { MessageService.ShowError("The addin '" + assembly + "' could not be loaded:\n" + ex.ToString()); } catch (FileLoadException ex) { @@ -92,6 +96,8 @@ namespace ICSharpCode.Core } } + public event EventHandler Loaded; + public Assembly LoadedAssembly { get { Load(); // load the assembly, if not already done diff --git a/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs b/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs index 96fa3be922..0d6bce8752 100644 --- a/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs +++ b/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs @@ -8,12 +8,12 @@ namespace ICSharpCode.Core.Presentation /// Stores details about command binding /// public class CommandBindingInfo - { - private UIElement contextInstance; - + { public CommandBindingInfo() { - ContextName = CommandsRegistry.DefaultContextName; + IsModifyed = true; + OldCommandBindings = new CommandBindingCollection(); + NewCommandBindings = new CommandBindingCollection(); } /// @@ -90,28 +90,105 @@ namespace ICSharpCode.Core.Presentation } /// - /// Name of the class which owns this binding + /// Store name of object owning this binding (can only be used with named objects) + /// + /// Named objects can be registered throgut + /// + public string OwnerInstanceName{ + get; set; + } + + private UIElement ownerInstance; + + /// + /// Stores instance of object which is owning this binding + /// + public UIElement OwnerInstance{ + get { + if(OwnerInstanceName != null && ownerInstance == null) { + ownerInstance = CommandsRegistry.GetNamedUIElementInstance(OwnerInstanceName); + } + + return ownerInstance; + } + set { + ownerInstance = value; + } + } + + /// + /// Assembly qualified name of the class owning this instance + /// + /// Named type can be registered throgut /// - public string ContextName{ + public string OwnerTypeName{ get; set; } + + private Type ownerType; /// - /// Instance of class which owns this binding + /// Stores type owning this binding /// - public UIElement Context { + public Type OwnerType { set { - contextInstance = value; + ownerType = value; } get { - if(contextInstance != null) { - return contextInstance; - } else { - UIElement context; - CommandsRegistry.contexts.TryGetValue(ContextName, out context); - - return context; + if(ownerType == null && OwnerTypeName != null) { + ownerType = Type.GetType(OwnerTypeName); + CommandsRegistry.RegisterNamedUIType(OwnerTypeName, ownerType); } + + return ownerType; + } + } + + /// + /// Default binding update handler update owner or type bindings (depending on input binding info type) + /// so they would always contain latest version + /// + private BindingsUpdatedHandler defaultCommandBindingHandler; + + /// + /// Default command binding handler. Updates command binding if binding info changes + /// + internal BindingsUpdatedHandler DefaultCommandBindingHandler + { + get { + if(defaultCommandBindingHandler == null && (OwnerTypeName != null || OwnerType != null)) { + defaultCommandBindingHandler = delegate { + if(OwnerType != null && IsModifyed) { + GenerateCommandBindings(); + + foreach(ManagedCommandBinding binding in OldCommandBindings) { + CommandsRegistry.RemoveClassCommandBinding(OwnerType, binding); + } + + foreach(ManagedCommandBinding binding in NewCommandBindings) { + CommandManager.RegisterClassCommandBinding(OwnerType, binding); + } + + IsModifyed = false; + } + }; + } else if(defaultCommandBindingHandler == null && (OwnerInstanceName != null || OwnerInstance != null)) { + defaultCommandBindingHandler = delegate { + if(OwnerInstance != null && IsModifyed) { + GenerateCommandBindings(); + + foreach(ManagedCommandBinding binding in OldCommandBindings) { + OwnerInstance.CommandBindings.Remove(binding); + } + + OwnerInstance.CommandBindings.AddRange(NewCommandBindings); + + IsModifyed = false; + } + }; + } + + return defaultCommandBindingHandler; } } @@ -136,6 +213,35 @@ namespace ICSharpCode.Core.Presentation { get; set; } + + /// + /// Indicates that generated command bindings are modified from last access + /// + public bool IsModifyed { + get; set; + } + + public void GenerateCommandBindings() + { + OldCommandBindings = NewCommandBindings; + + var managedCommandBinding = new ManagedCommandBinding(RoutedCommand); + managedCommandBinding.CanExecute += GeneratedCanExecuteEventHandler; + managedCommandBinding.Executed += GeneratedExecutedEventHandler; + + NewCommandBindings = new CommandBindingCollection(); + NewCommandBindings.Add(managedCommandBinding); + } + + internal CommandBindingCollection OldCommandBindings + { + get; set; + } + + internal CommandBindingCollection NewCommandBindings + { + get; set; + } internal void GeneratedExecutedEventHandler(object sender, ExecutedRoutedEventArgs e) { if(ExecutedEventHandler != null) { diff --git a/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs b/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs index 6f067afa8b..6cb2bb6197 100644 --- a/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs +++ b/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs @@ -7,6 +7,8 @@ using System.Threading; using System.Text; using System.Text.RegularExpressions; using System.Linq; +using System.Reflection; +using System.Collections.Specialized; namespace ICSharpCode.Core.Presentation { @@ -31,18 +33,111 @@ namespace ICSharpCode.Core.Presentation get; set; } + // Binding infos private static List commandBindings = new List(); private static List inputBidnings = new List(); + // Commands private static Dictionary routedCommands = new Dictionary(); internal static Dictionary commands = new Dictionary(); - internal static Dictionary contexts = new Dictionary(); - private static Dictionary>> commandBindingsUpdateHandlers = new Dictionary>>(); - private static Dictionary>> inputBindingsUpdateHandlers = new Dictionary>>(); - + // Update hanlers + private static Dictionary> classCommandBindingUpdateHandlers = new Dictionary>(); + private static Dictionary> instanceCommandBindingUpdateHandlers = new Dictionary>(); + private static Dictionary> classInputBindingUpdateHandlers = new Dictionary>(); + private static Dictionary> instanceInputBindingUpdateHandlers = new Dictionary>(); + + // Named instances and types + private static Dictionary namedUIInstances = new Dictionary(); + private static Dictionary namedUITypes = new Dictionary(); + + // Categories private static List categories = new List(); + /// + /// Register UI element instance accessible by unique name + /// + /// Instance name + /// Instance + public static void RegisterNamedUIElementInstance(string instanceName, UIElement element) + { + if(!namedUIInstances.ContainsKey(instanceName)){ + namedUIInstances.Add(instanceName, element); + + // If there are some bindings and update handlers already registered, + // but owner is not loaded then move these to arrays which holds bindings + // and update handlers of loaded instances + if(instanceCommandBindingUpdateHandlers.ContainsKey(instanceName)) { + foreach(var handler in instanceCommandBindingUpdateHandlers[instanceName]) { + RegisterInstanceCommandBindingsUpdateHandler(element, handler); + } + instanceCommandBindingUpdateHandlers.Remove(instanceName); + InvokeInstanceCommandBindingUpdateHandlers(element); + + foreach(var handler in instanceInputBindingUpdateHandlers[instanceName]) { + RegisterInstanceInputBindingsUpdateHandler(element, handler); + } + instanceInputBindingUpdateHandlers.Remove(instanceName); + InvokeInstanceInputBindingUpdateHandlers(element); + } + } + } + + /// + /// Get instance by unique instance name + /// + /// Instance name + /// + public static UIElement GetNamedUIElementInstance(string instanceName) + { + UIElement instance; + namedUIInstances.TryGetValue(instanceName, out instance); + + return instance; + } + + /// + /// Register UI type which can be accessible by name + /// + /// Type name + /// Type + public static void RegisterNamedUIType(string typeName, Type type) + { + if(!namedUITypes.ContainsKey(typeName)){ + namedUITypes.Add(typeName, type); + + // If any bindings or update handlers where assigned to the type + // before it was loaded using unique name move these to array + // holding type bindings and update handlers + if(classCommandBindingUpdateHandlers.ContainsKey(typeName)) { + foreach(var handler in classCommandBindingUpdateHandlers[typeName]) { + RegisterClassCommandBindingsUpdateHandler(type, handler); + } + classCommandBindingUpdateHandlers.Remove(typeName); + InvokeClassCommandBindingUpdateHandlers(type); + + foreach(var handler in classInputBindingUpdateHandlers[typeName]) { + RegisterClassInputBindingsUpdateHandler(type, handler); + } + classInputBindingUpdateHandlers.Remove(typeName); + InvokeClassInputBindingUpdateHandlers(type); + } + } + } + + /// + /// Get type by uniqe type name + /// + /// Type name + /// Type + public static Type GetNamedUIType(string typeName) + { + Type instance; + namedUITypes.TryGetValue(typeName, out instance); + + return instance; + } + /// /// Get reference to routed UI command by name /// @@ -121,7 +216,14 @@ namespace ICSharpCode.Core.Presentation public static void RegisterInputBinding(InputBindingInfo inputBindingInfo) { inputBidnings.Add(inputBindingInfo); - CommandsRegistry.InvokeCommandBindingUpdateHandlers(inputBindingInfo.ContextName, null); + + if(inputBindingInfo.OwnerTypeName != null || inputBindingInfo.OwnerType != null) { + RegisterClassDefaultInputBindingHandler(inputBindingInfo); + } else if (inputBindingInfo.OwnerInstanceName != null || inputBindingInfo.OwnerInstance != null) { + RegisterInstaceDefaultInputBindingHandler(inputBindingInfo); + } else { + throw new ArgumentException("Binding owner must be specified"); + } } /// @@ -134,233 +236,371 @@ namespace ICSharpCode.Core.Presentation } /// - /// Find input input bindings which satisfy provided arguments + /// Find input input binding infos which satisfy provided arguments /// /// Null arguments are ignored /// /// Context class full name /// Unregister binding assigned to specific context instance /// Routed UI command name - public static ICollection FindInputBindingInfos(string contextName, UIElement contextInstance, string routedCommandName) { + public static ICollection FindInputBindingInfos(string ownerTypeName, Type ownerType, string ownerInstanceName, UIElement ownerInstance, string routedCommandName) { var foundBindings = new List(); - for(int i = inputBidnings.Count - 1; i >= 0; i--) { - if((contextName == null || inputBidnings[i].ContextName == contextName) - && (contextInstance == null || inputBidnings[i].Context == null || inputBidnings[i].Context == contextInstance) - && (routedCommandName == null || inputBidnings[i].RoutedCommandName == routedCommandName)) { - foundBindings.Add(inputBidnings[i]); + + foreach(var binding in inputBidnings) { + if( (ownerInstanceName == null || binding.OwnerInstanceName == ownerInstanceName) + && (ownerInstance == null || binding.OwnerInstance == ownerInstance) + && (ownerTypeName == null || binding.OwnerTypeName == ownerTypeName) + && (ownerType == null || binding.OwnerType == ownerType) + && (routedCommandName == null || binding.RoutedCommandName == routedCommandName)) { + + foundBindings.Add(binding); } } return foundBindings; } - + /// - /// Register delegate which will be invoked on change in input bindings in specified context + /// Remove input binding associated with type /// - /// Context class full name - /// Register update handler which will trigger only if input bindings registered for this object where triggered - /// Update handler delegate - public static void RegisterInputBindingUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) { - if(contextInstance == null) { - contextInstance = NullUIElement; + /// Owner type + /// Input binding + public static void RemoveClassInputBinding(Type ownerType, InputBinding inputBinding) + { + var fieldInfo = typeof(CommandManager).GetField("_classInputBindings", BindingFlags.Static | BindingFlags.NonPublic); + var fieldData = (HybridDictionary)fieldInfo.GetValue(null); + var classInputBindings = (InputBindingCollection)fieldData[ownerType]; + + if(classInputBindings != null) { + classInputBindings.Remove(inputBinding); } - - if(!inputBindingsUpdateHandlers.ContainsKey(contextName)) { - inputBindingsUpdateHandlers.Add(contextName, new Dictionary>()); + } + + /// + /// Remove command binding associated with type + /// + /// + /// + public static void RemoveClassCommandBinding(Type ownerType, CommandBinding commandBinding) + { + var fieldInfo = typeof(CommandManager).GetField("_classCommandBindings", BindingFlags.Static | BindingFlags.NonPublic); + var fieldData = (HybridDictionary)fieldInfo.GetValue(null); + var classCommandBindings = (CommandBindingCollection)fieldData[ownerType]; + + if(classCommandBindings != null) { + classCommandBindings.Remove(commandBinding); } + } + + /// + /// Register command binding by specifying command binding parameters + /// + /// Command binding parameters + public static void RegisterCommandBinding(CommandBindingInfo commandBindingInfo) { + commandBindings.Add(commandBindingInfo); + commandBindingInfo.GenerateCommandBindings(); - if(!inputBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) { - inputBindingsUpdateHandlers[contextName].Add(contextInstance, new List()); + if(commandBindingInfo.OwnerTypeName != null || commandBindingInfo.OwnerType != null) { + RegisterClassDefaultCommandBindingHandler(commandBindingInfo); + } else if (commandBindingInfo.OwnerInstanceName != null || commandBindingInfo.OwnerInstance != null) { + RegisterInstaceDefaultCommandBindingHandler(commandBindingInfo); + } else { + throw new ArgumentException("Binding owner must be specified"); } - - inputBindingsUpdateHandlers[contextName][contextInstance].Add(handler); } - + /// - /// Remove input bindings update handler + /// Unregister command binding /// - /// Context class full name - /// Unregister update handler which was triggered only if input bindings registered for specific instance where updated - /// Update handler delegate - public static void UnregisterInputBindingUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) { - if(contextInstance == null) { - contextInstance = NullUIElement; - } - if(!inputBindingsUpdateHandlers.ContainsKey(contextName)) { - if(!inputBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) { - for(int i = inputBindingsUpdateHandlers[contextName][contextInstance].Count - 1; i >= 0; i++) { - if(inputBindingsUpdateHandlers[contextName][contextInstance][i] == handler) { - inputBindingsUpdateHandlers[contextName][contextInstance].RemoveAt(i); - } - } + /// Command binding parameters + public static void UnregisterCommandBinding(CommandBindingInfo commandBindingInfo) { + commandBindings.Remove(commandBindingInfo); + + // Remove command bindings + if(commandBindingInfo.OwnerType != null) { + foreach(ManagedCommandBinding binding in commandBindingInfo.OldCommandBindings) { + RemoveClassCommandBinding(commandBindingInfo.OwnerType, binding); + } + + foreach(ManagedCommandBinding binding in commandBindingInfo.NewCommandBindings) { + RemoveClassCommandBinding(commandBindingInfo.OwnerType, binding); + } + } else if (commandBindingInfo.OwnerInstance != null) { + foreach(ManagedCommandBinding binding in commandBindingInfo.OldCommandBindings) { + commandBindingInfo.OwnerInstance.CommandBindings.Remove(binding); + } + + foreach(ManagedCommandBinding binding in commandBindingInfo.NewCommandBindings) { + commandBindingInfo.OwnerInstance.CommandBindings.Remove(binding); } } } + #region Register bindings update handler /// - /// Invoke registered input bindings update handlers registered in specified context + /// Register command binding update handler which is triggered when input bindings associated + /// with specified type change /// - /// Context class full name - public static void InvokeInputBindingUpdateHandlers(string contextName, UIElement contextInstance) { - if(contextInstance == null) { - contextInstance = NullUIElement; + /// Owner type + /// Update handler + public static void RegisterClassCommandBindingsUpdateHandler(Type ownerType, BindingsUpdatedHandler handler) + { + RegisterClassCommandBindingsUpdateHandler(ownerType.AssemblyQualifiedName, handler); + } + + /// + /// Register command binding update handler which is triggered when input bindings associated + /// with specified type change + /// + /// Owner type name + /// Update handler + public static void RegisterClassCommandBindingsUpdateHandler(string ownerTypeName, BindingsUpdatedHandler handler) + { + if(!classCommandBindingUpdateHandlers.ContainsKey(ownerTypeName)) { + classCommandBindingUpdateHandlers.Add(ownerTypeName, new List()); } - if(contextName != null) { - if(inputBindingsUpdateHandlers.ContainsKey(contextName)) { - if(contextInstance == NullUIElement) { - foreach(var instanceHandlers in inputBindingsUpdateHandlers[contextName]) { - foreach(var handler in instanceHandlers.Value) { - if(handler != null) { - ((BindingsUpdatedHandler)handler).Invoke(); - } - } - } - } - } else if(inputBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) { - foreach(var handler in inputBindingsUpdateHandlers[contextName][contextInstance]) { - if(handler != null) { - ((BindingsUpdatedHandler)handler).Invoke(); - } - } - } + if(!classCommandBindingUpdateHandlers[ownerTypeName].Contains(handler)) { + classCommandBindingUpdateHandlers[ownerTypeName].Add(handler); + } + } + + /// + /// Register command binding update handler which is triggered when input bindings associated + /// with specified instance change + /// + /// Owner instance name + /// Update handler + public static void RegisterInstanceCommandBindingsUpdateHandler(string instanceName, BindingsUpdatedHandler handler) + { + var instance = GetNamedUIElementInstance(instanceName); + if(instance != null) { + RegisterInstanceCommandBindingsUpdateHandler(instance, handler); } else { - foreach(var contextHandlers in inputBindingsUpdateHandlers) { - foreach(var instanceHandlers in contextHandlers.Value) { - foreach(var handler in instanceHandlers.Value) { - if(handler != null) { - ((BindingsUpdatedHandler)handler).Invoke(); - } - } - } + if(!instanceCommandBindingUpdateHandlers.ContainsKey(instanceName)) { + instanceCommandBindingUpdateHandlers.Add(instanceName, new List()); } + + instanceCommandBindingUpdateHandlers[instanceName].Add(handler); } } /// - /// Remove all managed input bindings from + /// Register command binding update handler which is triggered when input bindings associated + /// with specified instance change /// - /// Input binding cllection containing managed input bindings - public static void RemoveManagedInputBindings(InputBindingCollection inputBindingCollection) { - for(int i = inputBindingCollection.Count - 1; i >= 0; i--) { - if(inputBindingCollection[i] is ManagedInputBinding) { - inputBindingCollection.RemoveAt(i); - } + /// Owner instance + /// Update handler + public static void RegisterInstanceCommandBindingsUpdateHandler(UIElement instance, BindingsUpdatedHandler handler) + { + if(!instanceCommandBindingUpdateHandlers.ContainsKey(instance)) { + instanceCommandBindingUpdateHandlers.Add(instance, new List()); } + + instanceCommandBindingUpdateHandlers[instance].Add(handler); + } + + /// + /// Register input binding update handler which is triggered when input bindings associated + /// with specified type change + /// + /// Owner type + /// Update handler + public static void RegisterClassInputBindingsUpdateHandler(Type ownerType, BindingsUpdatedHandler handler) + { + RegisterClassInputBindingsUpdateHandler(ownerType.AssemblyQualifiedName, handler); } /// - /// Register command binding by specifying command binding parameters + /// Register input binding update handler which is triggered when input bindings associated + /// with specified type change /// - /// Command binding parameters - public static void RegisterCommandBinding(CommandBindingInfo commandBindingInfo) { - commandBindings.Add(commandBindingInfo); + /// Owner type name + /// Update handler + public static void RegisterClassInputBindingsUpdateHandler(string ownerTypeName, BindingsUpdatedHandler handler) + { + if(!classInputBindingUpdateHandlers.ContainsKey(ownerTypeName)) { + classInputBindingUpdateHandlers.Add(ownerTypeName, new List()); + } + + if(!classInputBindingUpdateHandlers[ownerTypeName].Contains(handler)) { + classInputBindingUpdateHandlers[ownerTypeName].Add(handler); + } } /// - /// Unregister command binding + /// Register input binding update handler which is triggered when input bindings associated + /// with specified instance change /// - /// Command binding parameters - public static void UnregisterCommandBinding(CommandBindingInfo commandBindingInfo) { - commandBindings.Remove(commandBindingInfo); + /// Owner instance name + /// Update handler + public static void RegisterInstanceInputBindingsUpdateHandler(string instanceName, BindingsUpdatedHandler handler) + { + var instance = GetNamedUIElementInstance(instanceName); + if(instance != null) { + RegisterInstanceInputBindingsUpdateHandler(instance, handler); + } else { + if(!instanceInputBindingUpdateHandlers.ContainsKey(instanceName)) { + instanceInputBindingUpdateHandlers.Add(instanceName, new List()); + } + + instanceInputBindingUpdateHandlers[instanceName].Add(handler); + } } /// - /// Register delegate which will be invoked on any chage in command bindings of specified context + /// Register input binding update handler which is triggered when input bindings associated + /// with specified instance change /// - /// Context class full name - /// Register update handler which is triggered only if input bindings registered for specific instance are updated - /// Update handler delegate - public static void RegisterCommandBindingsUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) { - if(contextInstance == null) { - contextInstance = NullUIElement; + /// Owner instance + /// Update handler + public static void RegisterInstanceInputBindingsUpdateHandler(UIElement instance, BindingsUpdatedHandler handler) + { + if(!instanceInputBindingUpdateHandlers.ContainsKey(instance)) { + instanceInputBindingUpdateHandlers.Add(instance, new List()); } - if(!commandBindingsUpdateHandlers.ContainsKey(contextName)) { - commandBindingsUpdateHandlers.Add(contextName, new Dictionary>()); + + instanceInputBindingUpdateHandlers[instance].Add(handler); + } + #endregion + + #region Invoke binding update handlers + + + /// + /// Invoke all inbut binding update handlers + /// + public static void InvokeInputBindingUpdateHandlers() + { + foreach(var instanceHandlers in instanceInputBindingUpdateHandlers) { + foreach(var handler in instanceHandlers.Value) { + handler.Invoke(); + } } - if(!commandBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) { - commandBindingsUpdateHandlers[contextName].Add(contextInstance, new List()); + foreach(var classHandlers in classInputBindingUpdateHandlers) { + foreach(var handler in classHandlers.Value) { + handler.Invoke(); + } + } + } + + /// + /// Invoke all command binding update handlers + /// + public static void InvokeCommandBindingUpdateHandlers() + { + foreach(var instanceHandlers in instanceCommandBindingUpdateHandlers) { + foreach(var handler in instanceHandlers.Value) { + handler.Invoke(); + } } - commandBindingsUpdateHandlers[contextName][contextInstance].Add(handler); + foreach(var classHandlers in classCommandBindingUpdateHandlers) { + foreach(var handler in classHandlers.Value) { + handler.Invoke(); + } + } } - + /// - /// Remove handler command bindings update handler + /// Invoke command binding update handlers associated with UI element instance /// - /// Context class full name - /// Unregister update handler which was triggered only if input bindings registered for specific instance were updated - /// Update handler delegate - public static void UnregisterCommandBindingsUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) { - if(contextInstance == null) { - contextInstance = NullUIElement; - } - if(commandBindingsUpdateHandlers.ContainsKey(contextName)) { - if(commandBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) { - for(int i = commandBindingsUpdateHandlers[contextName][contextInstance].Count - 1; i >= 0; i--) { - if(commandBindingsUpdateHandlers[contextName][contextInstance][i] == handler) { - commandBindingsUpdateHandlers[contextName][contextInstance].RemoveAt(i); - } - } + /// Owner instance + public static void InvokeInstanceCommandBindingUpdateHandlers(UIElement owner) + { + if(instanceCommandBindingUpdateHandlers.ContainsKey(owner)) { + foreach(var handler in instanceCommandBindingUpdateHandlers[owner]) { + handler.Invoke(); } } } /// - /// Invoke registered command bindings update handlers registered in specified context + /// Invoke command binding update handlers associated with UI element instance /// - /// Context class full name - /// Invoke update handlers which handle update only in specifyc context - public static void InvokeCommandBindingUpdateHandlers(string contextName, UIElement contextInstance) { - if(contextInstance == null) { - contextInstance = NullUIElement; + /// Owner instance name + public static void InvokeInstanceCommandBindingUpdateHandlers(string ownerName) + { + if(instanceCommandBindingUpdateHandlers.ContainsKey(ownerName)) { + foreach(var handler in instanceCommandBindingUpdateHandlers[ownerName]) { + handler.Invoke(); + } } - - if(contextName != null) { - if(commandBindingsUpdateHandlers.ContainsKey(contextName)) { - if(contextInstance == NullUIElement) { - foreach(var instanceHandlers in commandBindingsUpdateHandlers[contextName]) { - foreach(var handler in instanceHandlers.Value) { - if(handler != null) { - ((BindingsUpdatedHandler)handler).Invoke(); - } - } - } - } else if(commandBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) { - foreach(var handler in commandBindingsUpdateHandlers[contextName][contextInstance]) { - if(handler != null) { - ((BindingsUpdatedHandler)handler).Invoke(); - } - } - } + } + + /// + /// Invoke command binding update handlers associated with UI element type + /// + /// Owner type + public static void InvokeClassCommandBindingUpdateHandlers(Type ownerType) + { + InvokeClassCommandBindingUpdateHandlers(ownerType.AssemblyQualifiedName); + } + + /// + /// Invoke command binding update handlers associated with UI element type + /// + /// Owner type name + public static void InvokeClassCommandBindingUpdateHandlers(string ownerTypeName) + { + if(instanceCommandBindingUpdateHandlers.ContainsKey(ownerTypeName)) { + foreach(var handler in classCommandBindingUpdateHandlers[ownerTypeName]) { + handler.Invoke(); } - } else { - foreach(var contextHandlers in commandBindingsUpdateHandlers) { - foreach(var instanceHandlers in contextHandlers.Value) { - foreach(var handler in instanceHandlers.Value) { - if(handler != null) { - ((BindingsUpdatedHandler)handler).Invoke(); - } - } - } + } + } + + /// + /// Invoke input binding update handlers associated with UI element instance + /// + /// Owner instance + public static void InvokeInstanceInputBindingUpdateHandlers(UIElement owner) + { + if(instanceInputBindingUpdateHandlers.ContainsKey(owner)) { + foreach(var handler in instanceInputBindingUpdateHandlers[owner]) { + handler.Invoke(); } } } /// - /// Remove all managed command bindings from + /// Invoke input binding update handlers associated with UI element instance /// - /// Command binding cllection containing managed input bindings - public static void RemoveManagedCommandBindings(CommandBindingCollection commandBindingsCollection) { - for(int i = commandBindingsCollection.Count - 1; i >= 0; i--) { - if(commandBindingsCollection[i] is ManagedCommandBinding) { - commandBindingsCollection.RemoveAt(i); + /// Owner instance name + public static void InvokeInstanceInputBindingUpdateHandlers(string ownerName) + { + if(instanceInputBindingUpdateHandlers.ContainsKey(ownerName)) { + foreach(var handler in instanceInputBindingUpdateHandlers[ownerName]) { + handler.Invoke(); } } } + /// + /// Invoke input binding update handlers associated with UI element type + /// + /// Owner type + public static void InvokeClassInputBindingUpdateHandlers(Type ownerType) + { + InvokeClassInputBindingUpdateHandlers(ownerType.AssemblyQualifiedName); + } + + /// + /// Invoke input binding update handlers associated with UI element type + /// + /// Owner type name + public static void InvokeClassInputBindingUpdateHandlers(string ownerTypeName) + { + if(instanceInputBindingUpdateHandlers.ContainsKey(ownerTypeName)) { + foreach(var handler in instanceInputBindingUpdateHandlers[ownerTypeName]) { + handler.Invoke(); + } + } + } + #endregion + /// /// Load all registered commands in add-in /// @@ -398,15 +638,6 @@ namespace ICSharpCode.Core.Presentation } } - /// - /// Register binding owner instance which can be identified by unique name - /// - /// Context class full name - /// Context class instance - public static void LoadContext(string contextName, UIElement context) { - contexts[contextName] = context; - } - /// /// Get list of all command bindings which satisfy provided parameters /// @@ -417,12 +648,14 @@ namespace ICSharpCode.Core.Presentation /// Context class full name /// Context class full name /// Collection of managed command bindings - public static ICollection FindCommandBindingInfos(string contextName, UIElement contextInstance, string routedCommandName, string className) { + public static ICollection FindCommandBindingInfos(string ownerTypeName, Type ownerType, string ownerInstanceName, UIElement ownerInstance, string routedCommandName, string className) { var foundBindings = new List(); foreach(var binding in commandBindings) { - if((contextName == null || binding.ContextName == contextName) - && (contextInstance == null || binding.Context == null || binding.Context == contextInstance) + if( (ownerInstanceName == null || binding.OwnerInstanceName == ownerInstanceName) + && (ownerInstance == null || binding.OwnerInstance == ownerInstance) + && (ownerTypeName == null || binding.OwnerTypeName == ownerTypeName) + && (ownerType == null || binding.OwnerType == ownerType) && (routedCommandName == null || binding.RoutedCommandName == routedCommandName) && (className == null || binding.ClassName == className)) { @@ -434,51 +667,6 @@ namespace ICSharpCode.Core.Presentation } - /// - /// Get list of all command bindings which satisfy provided parameters - /// - /// Null arguments are ignored - /// - /// Context class full name - /// Get command bindings assigned only to specific context - /// Context class full name - /// Context class full name - /// Collection of managed command bindings - public static CommandBindingCollection FindCommandBindings(string contextName, UIElement contextInstance, string routedCommandName, string className) { - var commandBindingInfos = FindCommandBindingInfos(contextName, contextInstance, routedCommandName, className); - - var bindings = new CommandBindingCollection(); - foreach(var binding in commandBindingInfos) { - var managedCommandBinding = new ManagedCommandBinding(binding.RoutedCommand); - managedCommandBinding.CanExecute += binding.GeneratedCanExecuteEventHandler; - managedCommandBinding.Executed += binding.GeneratedExecutedEventHandler; - - bindings.Add(managedCommandBinding); - } - - return bindings; - } - - /// - /// Get list of all input bindings which satisfy provided parameters - /// - /// Null arguments are ignored - /// - /// Context class full name - /// Get input bindings assigned only to specific context - /// Routed UI command name - public static InputBindingCollection FindInputBindings(string contextName, UIElement contextInstance, string routedCommandName) { - var inputBindingInfos = FindInputBindingInfos(contextName, contextInstance, routedCommandName); - - var bindings = new InputBindingCollection(); - foreach(var binding in inputBindingInfos) { - foreach(InputGesture bindingGesture in binding.Gestures) { - bindings.Add(new ManagedInputBinding(binding.RoutedCommand, bindingGesture)); - } - } - - return bindings; - } /// /// Get list of input gestures from all input bindings which satisfy provided parameters @@ -489,12 +677,12 @@ namespace ICSharpCode.Core.Presentation /// Get gestures assigned only to specific context /// Routed UI command name /// Gesture - public static InputGestureCollection FindInputGestures(string contextName, UIElement contextInstance, string routedCommandName) { - var bindings = FindInputBindings(contextName, contextInstance, routedCommandName); + public static InputGestureCollection FindInputGestures(string ownerTypeName, Type ownerType, string ownerInstanceName, UIElement ownerInstance, string routedCommandName) { + var bindings = FindInputBindingInfos(ownerTypeName, ownerType, ownerInstanceName, ownerInstance, routedCommandName); var gestures = new InputGestureCollection(); - foreach(InputBinding binding in bindings) { - gestures.Add(binding.Gesture); + foreach(InputBindingInfo bindingInfo in bindings) { + gestures.AddRange(bindingInfo.Gestures); } return gestures; @@ -540,5 +728,77 @@ namespace ICSharpCode.Core.Presentation return registeredCategories; } + + /// + /// Register default command binding update hander which will keep instance command + /// bindings upated + /// + /// Command binding info + private static void RegisterInstaceDefaultCommandBindingHandler(CommandBindingInfo commandBindingInfo) + { + if(commandBindingInfo.DefaultCommandBindingHandler != null) { + commandBindingInfo.DefaultCommandBindingHandler.Invoke(); + } + + if(commandBindingInfo.OwnerInstanceName != null && commandBindingInfo.OwnerInstance == null) { + RegisterInstanceCommandBindingsUpdateHandler(commandBindingInfo.OwnerInstanceName, commandBindingInfo.DefaultCommandBindingHandler); + } else if(commandBindingInfo.OwnerInstance != null) { + RegisterInstanceCommandBindingsUpdateHandler(commandBindingInfo.OwnerInstance, commandBindingInfo.DefaultCommandBindingHandler); + } + } + + /// + /// Register default command binding update hander which will keep type command + /// bindings upated + /// + /// Command binding info + private static void RegisterClassDefaultCommandBindingHandler(CommandBindingInfo commandBindingInfo) + { + if(commandBindingInfo.DefaultCommandBindingHandler != null) { + commandBindingInfo.DefaultCommandBindingHandler.Invoke(); + } + + if(commandBindingInfo.OwnerTypeName != null && commandBindingInfo.OwnerType == null) { + RegisterClassCommandBindingsUpdateHandler(commandBindingInfo.OwnerTypeName, commandBindingInfo.DefaultCommandBindingHandler); + } else if(commandBindingInfo.OwnerType != null) { + RegisterClassCommandBindingsUpdateHandler(commandBindingInfo.OwnerType, commandBindingInfo.DefaultCommandBindingHandler); + } + } + + /// + /// Register default input binding update hander which will keep instance command + /// bindings upated + /// + /// Input binding info + private static void RegisterInstaceDefaultInputBindingHandler(InputBindingInfo inputBindingInfo) + { + if(inputBindingInfo.DefaultInputBindingHandler != null) { + inputBindingInfo.DefaultInputBindingHandler.Invoke(); + } + + if(inputBindingInfo.OwnerInstanceName != null && inputBindingInfo.OwnerInstance == null) { + RegisterInstanceInputBindingsUpdateHandler(inputBindingInfo.OwnerInstanceName, inputBindingInfo.DefaultInputBindingHandler); + } else if(inputBindingInfo.OwnerInstance != null) { + RegisterInstanceInputBindingsUpdateHandler(inputBindingInfo.OwnerInstance, inputBindingInfo.DefaultInputBindingHandler); + } + } + + /// + /// Register default input binding update hander which will keep type command + /// bindings upated + /// + /// Input binding info + private static void RegisterClassDefaultInputBindingHandler(InputBindingInfo inputBindingInfo) + { + if(inputBindingInfo.DefaultInputBindingHandler != null) { + inputBindingInfo.DefaultInputBindingHandler.Invoke(); + } + + if(inputBindingInfo.OwnerTypeName != null && inputBindingInfo.OwnerType == null) { + RegisterClassInputBindingsUpdateHandler(inputBindingInfo.OwnerTypeName, inputBindingInfo.DefaultInputBindingHandler); + } else if(inputBindingInfo.OwnerType != null) { + RegisterClassInputBindingsUpdateHandler(inputBindingInfo.OwnerType, inputBindingInfo.DefaultInputBindingHandler); + } + } } } diff --git a/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs b/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs index 698c9e5745..624aa3b0af 100644 --- a/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs +++ b/src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs @@ -39,8 +39,6 @@ namespace ICSharpCode.Core.Presentation { var descriptors = AddInTree.BuildItems(path, caller, false); foreach(var desc in descriptors) { - var contextName = !string.IsNullOrEmpty(desc.Context) ? desc.Context : CommandsRegistry.DefaultContextName; - // If routed with such name is not registered register routed command with text same as name if(CommandsRegistry.GetRoutedUICommand(desc.Command) == null) { var commandText = string.IsNullOrEmpty(desc.CommandText) ? desc.Command : desc.CommandText; @@ -48,7 +46,15 @@ namespace ICSharpCode.Core.Presentation } var commandBindingInfo = new CommandBindingInfo(); - commandBindingInfo.ContextName = contextName; + + if(!string.IsNullOrEmpty(desc.OwnerInstanceName)) { + commandBindingInfo.OwnerInstanceName = desc.OwnerInstanceName; + } else if(!string.IsNullOrEmpty(desc.OwnerTypeName)) { + commandBindingInfo.OwnerTypeName = desc.OwnerTypeName; + } else { + commandBindingInfo.OwnerTypeName = CommandsRegistry.DefaultContextName; + } + commandBindingInfo.RoutedCommandName = desc.Command; commandBindingInfo.ClassName = desc.Class; commandBindingInfo.AddIn = desc.Codon.AddIn; @@ -60,7 +66,15 @@ namespace ICSharpCode.Core.Presentation var gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromString(desc.Gestures); var inputBindingInfo = new InputBindingInfo(); - inputBindingInfo.ContextName = contextName; + + if(!string.IsNullOrEmpty(desc.OwnerInstanceName)) { + inputBindingInfo.OwnerInstanceName = desc.OwnerInstanceName; + } else if(!string.IsNullOrEmpty(desc.OwnerTypeName)) { + inputBindingInfo.OwnerTypeName = desc.OwnerTypeName; + } else { + inputBindingInfo.OwnerTypeName = CommandsRegistry.DefaultContextName; + } + inputBindingInfo.AddIn = desc.Codon.AddIn; inputBindingInfo.RoutedCommandName = desc.Command; inputBindingInfo.Gestures = gestures; @@ -83,10 +97,17 @@ namespace ICSharpCode.Core.Presentation var descriptors = AddInTree.BuildItems(path, caller, false); foreach(var desc in descriptors) { var gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromString(desc.Gestures); - var contextName = !string.IsNullOrEmpty(desc.Context) ? desc.Context : CommandsRegistry.DefaultContextName; var inputBindingInfo = new InputBindingInfo(); - inputBindingInfo.ContextName = contextName; + + if(!string.IsNullOrEmpty(desc.OwnerInstanceName)) { + inputBindingInfo.OwnerInstanceName = desc.OwnerInstanceName; + } else if(!string.IsNullOrEmpty(desc.OwnerTypeName)) { + inputBindingInfo.OwnerTypeName = desc.OwnerTypeName; + } else { + inputBindingInfo.OwnerTypeName = CommandsRegistry.DefaultContextName; + } + inputBindingInfo.AddIn = desc.Codon.AddIn; inputBindingInfo.RoutedCommandName = desc.Command; inputBindingInfo.Gestures = gestures; diff --git a/src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs b/src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs index 1e0cb6468e..5303b35d7c 100644 --- a/src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs +++ b/src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs @@ -5,95 +5,183 @@ using System.Collections.Generic; namespace ICSharpCode.Core.Presentation { - /// - /// Stores details about input binding - /// - public class InputBindingInfo - { - private UIElement contextInstance; - - public InputBindingInfo() { - ContextName = CommandsRegistry.DefaultContextName; - Categories = new List(); - } - - /// - /// Context class full name - /// - /// Described binding will be valid in this context - /// - public string ContextName { - get; set; - } - - /// - /// Context class instance - /// - /// Described binding will be valid in this context - /// - public UIElement Context { - get { - if(contextInstance != null) { - return contextInstance; - } else { - UIElement context; - CommandsRegistry.contexts.TryGetValue(ContextName, out context); - - return context; - } + /// + /// Stores details about input binding + /// + public class InputBindingInfo + { + public InputBindingInfo() { + IsModifyed = true; + OldInputBindings = new InputBindingCollection(); + NewInputBindings = new InputBindingCollection(); + + Categories = new List(); + } + + public string OwnerInstanceName{ + get; set; + } + + private UIElement ownerInstance; + + public UIElement OwnerInstance{ + get { + if(OwnerInstanceName != null && ownerInstance == null) { + ownerInstance = CommandsRegistry.GetNamedUIElementInstance(OwnerInstanceName); } + + return ownerInstance; } - - - /// - /// Routed command text - /// - /// Override routed command text when displaying to user - /// - /// - public string RoutedCommandText { - get; set; + set { + ownerInstance = value; } - - - /// - /// Add-in to which registered this input binding - /// - public AddIn AddIn { - get; set; + } + + public string OwnerTypeName{ + get; set; + } + + private Type ownerType; + + public Type OwnerType { + set { + ownerType = value; } - - /// - /// Routed command name - /// - /// Described binding triggers this routed command - /// - /// - public string RoutedCommandName { - get; set; + get { + if(ownerType == null && OwnerTypeName != null) { + ownerType = Type.GetType(OwnerTypeName); + CommandsRegistry.RegisterNamedUIType(OwnerTypeName, ownerType); + } + + return ownerType; } + } + + /// + /// Routed command text + /// + /// Override routed command text when displaying to user + /// + /// + public string RoutedCommandText { + get; set; + } - /// - /// Routed command instance - /// - /// Described binding triggers this routed command - /// - /// - public RoutedUICommand RoutedCommand { - get { - return CommandsRegistry.GetRoutedUICommand(RoutedCommandName); + + /// + /// Add-in to which registered this input binding + /// + public AddIn AddIn { + get; set; + } + + /// + /// Gestures which triggers this binding + /// + public InputGestureCollection Gestures { + get; set; + } + + /// + /// Routed command name + /// + /// Described binding triggers this routed command + /// + /// + public string RoutedCommandName { + get; set; + } + + /// + /// Routed command instance + /// + /// Described binding triggers this routed command + /// + /// + public RoutedUICommand RoutedCommand { + get { + return CommandsRegistry.GetRoutedUICommand(RoutedCommandName); + } + } + + private BindingsUpdatedHandler defaultInputBindingHandler; + + /// + /// Default binding update handler update owner or type bindings (depending on input binding info type) + /// so they would always contain latest version + /// + public BindingsUpdatedHandler DefaultInputBindingHandler + { + get { + if(defaultInputBindingHandler == null && (OwnerTypeName != null || OwnerType != null)) { + defaultInputBindingHandler = delegate { + if(OwnerType != null && IsModifyed) { + GenerateInputBindings(); + + foreach(ManagedInputBinding binding in OldInputBindings) { + CommandsRegistry.RemoveClassInputBinding(OwnerType, binding); + } + + foreach(ManagedInputBinding binding in NewInputBindings) { + CommandManager.RegisterClassInputBinding(OwnerType, binding); + } + + IsModifyed = false; + } + }; + } else if(defaultInputBindingHandler == null && (OwnerInstanceName != null || OwnerInstance != null)) { + defaultInputBindingHandler = delegate { + if(OwnerInstance != null && IsModifyed) { + GenerateInputBindings(); + + foreach(ManagedInputBinding binding in NewInputBindings) { + OwnerInstance.InputBindings.Remove(binding); + } + + OwnerInstance.InputBindings.AddRange(NewInputBindings); + + IsModifyed = false; + } + }; } + + return defaultInputBindingHandler; } + } + + /// + /// List of categories associated with input binding + /// + public List Categories { + get; private set; + } - /// - /// Gestures which triggers this binding - /// - public InputGestureCollection Gestures { - get; set; - } + /// + /// Indicates whether generated input bindings where modified from last access + /// + public bool IsModifyed { + get; set; + } + + public void GenerateInputBindings() + { + OldInputBindings = NewInputBindings; - public List Categories { - get; private set; + NewInputBindings = new InputBindingCollection(); + foreach(InputGesture gesture in Gestures) { + var managedInputBinding = new ManagedInputBinding(RoutedCommand, gesture); + NewInputBindings.Add(managedInputBinding); } } + + internal InputBindingCollection OldInputBindings + { + get; set; + } + + internal InputBindingCollection NewInputBindings + { + get; set; + } + } } diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs index cd875ce082..3bb34d1c1a 100644 --- a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs +++ b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs @@ -140,13 +140,12 @@ namespace ICSharpCode.Core.Presentation if(!codon.Properties.Contains("command") && (codon.Properties.Contains("link") || codon.Properties.Contains("class"))) { var commandBindingInfo = new CommandBindingInfo(); commandBindingInfo.AddIn = codon.AddIn; - commandBindingInfo.ContextName = CommandsRegistry.DefaultContextName; + commandBindingInfo.OwnerTypeName = CommandsRegistry.DefaultContextName; commandBindingInfo.Class = CommandWrapper.GetCommand(codon, caller, createCommand); commandBindingInfo.RoutedCommandName = routedCommandName; commandBindingInfo.IsLazy = true; CommandsRegistry.RegisterCommandBinding(commandBindingInfo); - CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContextName, null); } if(codon.Properties.Contains("shortcut")) { @@ -154,16 +153,19 @@ namespace ICSharpCode.Core.Presentation var inputBindingInfo = new InputBindingInfo(); inputBindingInfo.AddIn = codon.AddIn; inputBindingInfo.Categories.AddRange(CommandsRegistry.RegisterInputBindingCategories("Menu Items")); - inputBindingInfo.ContextName = CommandsRegistry.DefaultContextName; + inputBindingInfo.OwnerTypeName = CommandsRegistry.DefaultContextName; inputBindingInfo.RoutedCommandName = routedCommandName; inputBindingInfo.Gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromInvariantString(codon.Properties["gestures"]); CommandsRegistry.RegisterInputBinding(inputBindingInfo); - CommandsRegistry.RegisterInputBindingUpdateHandler(CommandsRegistry.DefaultContextName, null, delegate { - var updatedGestures = CommandsRegistry.FindInputGestures(null, null, routedCommandName); - this.InputGestureText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures); - }); - CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContextName, null); + + BindingsUpdatedHandler gesturesUpdateHandler = delegate { + var updatedGestures = CommandsRegistry.FindInputGestures(null, null, null, null, routedCommandName); + this.InputGestureText = (string)new InputGestureCollectionConverter().ConvertToInvariantString(updatedGestures); + }; + + gesturesUpdateHandler.Invoke(); + CommandsRegistry.RegisterClassInputBindingsUpdateHandler(CommandsRegistry.DefaultContextName, gesturesUpdateHandler); } } } diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs index 1c372c6e35..0e6a5b5c37 100644 --- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs +++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs @@ -50,13 +50,12 @@ namespace ICSharpCode.Core.Presentation if(!codon.Properties.Contains("command") && (codon.Properties.Contains("link") || codon.Properties.Contains("class"))) { var commandBindingInfo = new CommandBindingInfo(); commandBindingInfo.AddIn = codon.AddIn; - commandBindingInfo.ContextName = CommandsRegistry.DefaultContextName; + commandBindingInfo.OwnerTypeName = CommandsRegistry.DefaultContextName; commandBindingInfo.Class = CommandWrapper.GetCommand(codon, caller, createCommand); commandBindingInfo.RoutedCommandName = routedCommandName; commandBindingInfo.IsLazy = true; CommandsRegistry.RegisterCommandBinding(commandBindingInfo); - CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContextName, null); } if (codon.Properties.Contains("icon")) {