Browse Source

Fix exceptions when opening new pad from view menu

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4173 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts^2
Sergej Andrejev 16 years ago
parent
commit
e451c17012
  1. 8
      AddIns/ICSharpCode.SharpDevelop.addin
  2. 12
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  3. 29
      src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
  4. 17
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonPadContent.cs
  5. 22
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
  6. 18
      src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs
  7. 63
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs
  8. 296
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs
  9. 10
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs
  10. 14
      src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs
  11. 4
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs

8
AddIns/ICSharpCode.SharpDevelop.addin

@ -52,7 +52,6 @@ @@ -52,7 +52,6 @@
</Runtime>
<!-- Commands registry test
<Path name="/SharpDevelop/Workbench/RoutedUICommands">
<RoutedUICommand name="SDTestCommands.Test" text="Create new file" />
@ -65,8 +64,6 @@ @@ -65,8 +64,6 @@
<RoutedUICommand name="SDBuildCommands.AbortBuild" text="${res:XML.MainMenu.BuildMenu.AbortBuild}" />
<RoutedUICommand name="SDBuildCommands.EditConfigurationsCommand" text="${res:XML.MainMenu.BuildMenu.EditConfigurationsPlatforms}" />
<RoutedUICommand name="SDWindowCommands.SplitView" text="TODO: Split view" />
<RoutedUICommand name="SDProjectCommands.AddNewProjectToSolution" text="${res:ProjectComponent.ContextMenu.NewProject}" />
<RoutedUICommand name="SDProjectCommands.AddExitingProjectToSolution" text="${res:ProjectComponent.ContextMenu.ExistingProject}" />
<RoutedUICommand name="SDProjectCommands.AddExistingItemToSolution" text="${res:ProjectComponent.ContextMenu.AddItem}" />
@ -96,8 +93,10 @@ @@ -96,8 +93,10 @@
<RoutedUICommand name="SDSearchCommands.ClearBookmarks" text="${res:XML.MainMenu.SearchMenu.ClearBookmarks}" />
<RoutedUICommand name="SDSearchCommands.GotoLineNumber" text="${res:XML.MainMenu.SearchMenu.GotoLineNr}" />
<RoutedUICommand name="SDSearchCommands.GotoBrace" text="${res:XML.MainMenu.SearchMenu.GotoBrace}" />
<RoutedUICommand name="SDWindowCommands.SplitView" text="Split view" />
</Path>
-->
<Path name="/SharpDevelop/Workbench/CommandBindings">
<CommandBinding command="SDTestCommands.Test" class="ICSharpCode.SharpDevelop.Commands.TestCommand" gestures="Ctrl+M" />
@ -136,7 +135,6 @@ @@ -136,7 +135,6 @@
<CommandBinding command="SDSearchCommands.ClearBookmarks" class="ICSharpCode.SharpDevelop.Bookmarks.ClearBookmarks" />
<CommandBinding command="SDSearchCommands.GotoLineNumber" class="ICSharpCode.SharpDevelop.DefaultEditor.Commands.GotoLineNumber" gestures="Ctrl+G" />
<CommandBinding command="SDSearchCommands.GotoBrace" class="ICSharpCode.SharpDevelop.DefaultEditor.Commands.GotoMatchingBrace" gestures="Ctrl+B" />
</Path>
<Path name="/SharpDevelop/Workbench/InputBindings">

12
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -117,7 +117,13 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -117,7 +117,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
public CodeEditor()
{
this.CommandBindings.Add(new CommandBinding(SharpDevelopRoutedCommands.SplitView, OnSplitView));
var contextName = this.GetType().FullName;
CommandsRegistry.RegisterCommandBindingsUpdateHandler(contextName, this, CommandsRegistry.CreateCommandBindingUpdateHandler(CommandBindings, contextName, this));
CommandsRegistry.RegisterInputBindingUpdateHandler(contextName, this, CommandsRegistry.CreateInputBindingUpdateHandler(InputBindings, contextName, this));
CommandsRegistry.RegisterCommandBinding(contextName, this, "SDWindowCommands.SplitView", OnSplitView, OnCanSplitView);
CommandsRegistry.InvokeCommandBindingUpdateHandlers(contextName, this);
CommandsRegistry.InvokeInputBindingUpdateHandlers(contextName, this);
textMarkerService = new TextMarkerService(this);
iconBarManager = new IconBarManager();
@ -198,6 +204,10 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -198,6 +204,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
primaryTextEditor.Save(stream);
}
void OnCanSplitView(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
void OnSplitView(object sender, ExecutedRoutedEventArgs e)
{
if (secondaryTextEditor == null) {

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

@ -456,6 +456,8 @@ namespace ICSharpCode.SharpDevelop.Commands @@ -456,6 +456,8 @@ namespace ICSharpCode.SharpDevelop.Commands
get;
}
public List<string> bindingsAssigned = new List<string>();
public ICollection BuildItems(Codon codon, object owner)
{
ArrayList list = new ArrayList();
@ -467,33 +469,32 @@ namespace ICSharpCode.SharpDevelop.Commands @@ -467,33 +469,32 @@ namespace ICSharpCode.SharpDevelop.Commands
item.Icon = PresentationResourceService.GetPixelSnappedImage(padContent.Icon);
}
// Dynamicaly create routed UI command for loaded pad
var routedCommandName = "SDViewCommands.ShowView_" + padContent.Class;
var routedCommandText = "Show view " + MenuService.ConvertLabel(StringParser.Parse(padContent.Title));
CommandsRegistry.RegisterRoutedUICommand(routedCommandName, routedCommandText);
// Register command which will activate loaded tab
// TODO: fix this hack
if(!bindingsAssigned.Contains(routedCommandName)) {
// Dynamicaly create routed UI command to loaded pad and bindings for it
CommandsRegistry.RegisterRoutedUICommand(routedCommandName, routedCommandText);
CommandsRegistry.LoadCommand(routedCommandName, new BringPadToFrontCommand(padContent));
// Register command binding in workbench
CommandsRegistry.RegisterCommandBinding(CommandsRegistry.DefaultContext, routedCommandName, routedCommandName, null, false);
CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContext);
item.Command = CommandsRegistry.GetRoutedUICommand(routedCommandName);
CommandsRegistry.RegisterCommandBinding(CommandsRegistry.DefaultContext, null, routedCommandName, routedCommandName, null, false);
// If pad have shortcut specified add input binding
if (!string.IsNullOrEmpty(padContent.Shortcut)) {
var gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromString(padContent.Shortcut);
foreach(InputGesture gesture in gestures) {
CommandsRegistry.RegisterInputBinding(CommandsRegistry.DefaultContext, routedCommandName, gesture);
CommandsRegistry.RegisterInputBinding(CommandsRegistry.DefaultContext, null, routedCommandName, gesture);
}
}
item.InputGestureText = "M: " + padContent.Shortcut;
} else {
item.InputGestureText = "M: ";
bindingsAssigned.Add(routedCommandName);
}
CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContext);
CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContext, null);
CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContext, null);
item.InputGestureText = padContent.Shortcut;
item.Command = CommandsRegistry.GetRoutedUICommand(routedCommandName);
// item.Command = new BringPadToFrontCommand(padContent);
// if (!string.IsNullOrEmpty(padContent.Shortcut)) {

17
src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonPadContent.cs

@ -91,19 +91,10 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -91,19 +91,10 @@ namespace ICSharpCode.SharpDevelop.Gui
CommandsRegistry.LoadContext(contextName, (UIElement)Content);
CommandsRegistry.RegisterCommandBindingsUpdateHandler(contextName, delegate {
var bindings = CommandsRegistry.GetCommandBindings(contextName, null, null);
CommandsRegistry.RemoveManagedCommandBindings(CommandBindings);
CommandBindings.AddRange(bindings);
});
CommandsRegistry.RegisterInputBindingUpdateHandler(contextName, delegate {
var bindings = CommandsRegistry.GetInputBindings(contextName, null, null);
CommandsRegistry.RemoveManagedInputBindings(InputBindings);
InputBindings.AddRange(bindings);
});
CommandsRegistry.InvokeCommandBindingUpdateHandlers(contextName);
CommandsRegistry.InvokeInputBindingUpdateHandlers(contextName);
CommandsRegistry.RegisterCommandBindingsUpdateHandler(contextName, null, CommandsRegistry.CreateCommandBindingUpdateHandler(CommandBindings, contextName, null));
CommandsRegistry.RegisterInputBindingUpdateHandler(contextName, null, CommandsRegistry.CreateInputBindingUpdateHandler(InputBindings, contextName, null));
CommandsRegistry.InvokeCommandBindingUpdateHandlers(contextName, null);
CommandsRegistry.InvokeInputBindingUpdateHandlers(contextName, null);
}
}
}

22
src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs

@ -97,23 +97,11 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -97,23 +97,11 @@ namespace ICSharpCode.SharpDevelop.Gui
CommandsRegistry.LoadContext(contextName, (UIElement)Content);
CommandsRegistry.RegisterCommandBindingsUpdateHandler(
contextName,
delegate {
var bindings = CommandsRegistry.GetCommandBindings(contextName, null, null);
CommandsRegistry.RemoveManagedCommandBindings(CommandBindings);
CommandBindings.AddRange(bindings);
});
CommandsRegistry.RegisterInputBindingUpdateHandler(
contextName,
delegate {
var bindings = CommandsRegistry.GetInputBindings(contextName, null, null);
CommandsRegistry.RemoveManagedInputBindings(InputBindings);
InputBindings.AddRange(bindings);
});
CommandsRegistry.InvokeCommandBindingUpdateHandlers(contextName);
CommandsRegistry.InvokeInputBindingUpdateHandlers(contextName);
CommandsRegistry.RegisterCommandBindingsUpdateHandler(contextName, null, CommandsRegistry.CreateCommandBindingUpdateHandler(CommandBindings, contextName, null));
CommandsRegistry.RegisterInputBindingUpdateHandler(contextName, null, CommandsRegistry.CreateInputBindingUpdateHandler(InputBindings, contextName, null));
CommandsRegistry.InvokeCommandBindingUpdateHandlers(contextName, null);
CommandsRegistry.InvokeInputBindingUpdateHandlers(contextName, null);
}
}

18
src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs

@ -92,20 +92,10 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -92,20 +92,10 @@ namespace ICSharpCode.SharpDevelop.Gui
// Register context and load all commands from addin
CommandsRegistry.LoadAddinCommands(AddInTree.AddIns.FirstOrDefault(a => a.Name == "SharpDevelop"));
CommandsRegistry.RegisterCommandBindingsUpdateHandler(CommandsRegistry.DefaultContext, delegate {
var bindings = CommandsRegistry.GetCommandBindings(CommandsRegistry.DefaultContext, null, null);
CommandsRegistry.RemoveManagedCommandBindings(CommandBindings);
CommandBindings.AddRange(bindings);
});
CommandsRegistry.RegisterInputBindingUpdateHandler(CommandsRegistry.DefaultContext, delegate {
var bindings = CommandsRegistry.GetInputBindings(CommandsRegistry.DefaultContext, null, null);
CommandsRegistry.RemoveManagedInputBindings(InputBindings);
InputBindings.AddRange(bindings);
});
CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContext);
CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContext);
CommandsRegistry.RegisterCommandBindingsUpdateHandler(CommandsRegistry.DefaultContext, null, CommandsRegistry.CreateCommandBindingUpdateHandler(CommandBindings, CommandsRegistry.DefaultContext, null));
CommandsRegistry.RegisterInputBindingUpdateHandler(CommandsRegistry.DefaultContext, null, CommandsRegistry.CreateInputBindingUpdateHandler(InputBindings, CommandsRegistry.DefaultContext, null));
CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContext, null);
CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContext, null);
mainMenu.ItemsSource = MenuService.CreateMenuItems(this, this, mainMenuPath);

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

@ -9,6 +9,8 @@ namespace ICSharpCode.Core.Presentation @@ -9,6 +9,8 @@ namespace ICSharpCode.Core.Presentation
/// </summary>
public class CommandBindingInfo
{
private UIElement contextInstance;
/// <summary>
/// Constructor
/// </summary>
@ -25,6 +27,30 @@ namespace ICSharpCode.Core.Presentation @@ -25,6 +27,30 @@ namespace ICSharpCode.Core.Presentation
AddIn = addIn;
}
public CommandBindingInfo(string contextName, UIElement contextInstance, string routedCommandName, string className, AddIn addIn, bool isLazy) {
RoutedCommandName = routedCommandName;
ContextName = contextName;
ClassName = className;
IsLazy = isLazy;
AddIn = addIn;
this.contextInstance = contextInstance;
}
public CommandBindingInfo(string contextName, string routedCommandName, ExecutedRoutedEventHandler executedHandler, CanExecuteRoutedEventHandler canExecuteHandler) {
RoutedCommandName = routedCommandName;
ContextName = contextName;
this.executedEventHandler = executedHandler;
this.canExecutedEventHandler = canExecuteHandler;
}
public CommandBindingInfo(string contextName, UIElement contextInstance, string routedCommandName, ExecutedRoutedEventHandler executedHandler, CanExecuteRoutedEventHandler canExecuteHandler) {
RoutedCommandName = routedCommandName;
ContextName = contextName;
this.executedEventHandler = executedHandler;
this.canExecutedEventHandler = canExecuteHandler;
this.contextInstance = contextInstance;
}
/// <summary>
/// Routed command name
///
@ -101,12 +127,16 @@ namespace ICSharpCode.Core.Presentation @@ -101,12 +127,16 @@ namespace ICSharpCode.Core.Presentation
/// </summary>
public UIElement Context {
get {
if(contextInstance != null) {
return contextInstance;
} else {
UIElement context;
CommandsRegistry.contexts.TryGetValue(ContextName, out context);
return context;
}
}
}
/// <summary>
/// Lazy load
@ -118,5 +148,38 @@ namespace ICSharpCode.Core.Presentation @@ -118,5 +148,38 @@ namespace ICSharpCode.Core.Presentation
public bool IsLazy{
get; private set;
}
private ExecutedRoutedEventHandler executedEventHandler;
public void ExecutedEventHandler(object sender, ExecutedRoutedEventArgs e) {
if(executedEventHandler != null) {
executedEventHandler.Invoke(sender, e);
} else {
if(IsLazy && Class == null) {
AddIn.LoadRuntimeAssemblies();
var command = (ICommand)AddIn.CreateObject(ClassName);
CommandsRegistry.LoadCommand(ClassName, command);
}
if(Class != null) {
Class.Execute(e.Parameter);
}
}
}
private CanExecuteRoutedEventHandler canExecutedEventHandler;
public void CanExecuteEventHandler(object sender, CanExecuteRoutedEventArgs e) {
if(canExecutedEventHandler != null) {
canExecutedEventHandler.Invoke(sender, e);
} else {
if(IsLazy && Class == null) {
e.CanExecute = true;
} else if(Class == null) {
e.CanExecute = false;
} else {
e.CanExecute = Class.CanExecute(e.Parameter);
}
}
}
}
}

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

@ -14,6 +14,11 @@ namespace ICSharpCode.Core.Presentation @@ -14,6 +14,11 @@ namespace ICSharpCode.Core.Presentation
/// </summary>
public static class CommandsRegistry
{
/// <summary>
/// This element is used to represent null key in dictionary
/// </summary>
private static UIElement NullUIElement = new UIElement();
/// <summary>
/// Default application context.
///
@ -30,8 +35,8 @@ namespace ICSharpCode.Core.Presentation @@ -30,8 +35,8 @@ namespace ICSharpCode.Core.Presentation
internal static Dictionary<string, System.Windows.Input.ICommand> commands = new Dictionary<string, System.Windows.Input.ICommand>();
internal static Dictionary<string, UIElement> contexts = new Dictionary<string, UIElement>();
private static Dictionary<string, List<WeakReference>> commandBindingsUpdateHandlers = new Dictionary<string, List<WeakReference>>();
private static Dictionary<string, List<WeakReference>> inputBindingsUpdateHandlers = new Dictionary<string, List<WeakReference>>();
private static Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>> commandBindingsUpdateHandlers = new Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>>();
private static Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>> inputBindingsUpdateHandlers = new Dictionary<string, Dictionary<UIElement, List<BindingsUpdatedHandler>>>();
/// <summary>
/// Get reference to routed UI command by name
@ -46,19 +51,47 @@ namespace ICSharpCode.Core.Presentation @@ -46,19 +51,47 @@ namespace ICSharpCode.Core.Presentation
return null;
}
/// <summary>
/// Checks whether routed UI command registered
/// </summary>
/// <param name="routedCommandName">Routed command name</param>
/// <returns>Returns value specifting whether routed UI command is registered</returns>
public static bool IsRoutedUICommandRegistered(string routedCommandName) {
return GetRoutedUICommand(routedCommandName) != null;
}
/// <summary>
/// Register new routed command in the global registry
///
/// Routed command name should be uniq in SharpDevelop scope.
/// Use "." to emulate namespaces
/// Routed command name should be unique in SharpDevelop scope.
/// Use "." to organize commands into groups
/// </summary>
/// <param name="routedCommandName">Routed command name</param>
/// <param name="text">Short text describing command functionality</param>
public static void RegisterRoutedUICommand(string routedCommandName, string text) {
var routedCommand = new RoutedUICommand(text, routedCommandName, typeof(UIElement));
var routedCommand = new RoutedUICommand(text, routedCommandName, typeof(CommandsRegistry));
if(!routedCommands.ContainsKey(routedCommandName)) {
routedCommands.Add(routedCommandName, routedCommand);
} else {
var test = routedCommands[routedCommandName];
throw new IndexOutOfRangeException("Routed UI command with name " + routedCommandName + " is already registered");
}
}
/// <summary>
/// Register existing routed command in the global registry
///
/// Routed command then can be accessed
/// Routed command name should be uniq in SharpDevelop scope.
/// Use "." to organize commands into groups
/// </summary>
/// <param name="routedCommandName">Existing routed command</param>
public static void RegisterRoutedUICommand(RoutedUICommand existingRoutedUICommand) {
string routedCommandName = existingRoutedUICommand.OwnerType.Name + "." + existingRoutedUICommand.Name;
if(!routedCommands.ContainsKey(routedCommandName)) {
routedCommands.Add(existingRoutedUICommand.OwnerType.Name + "." + existingRoutedUICommand.Name, existingRoutedUICommand);
} else {
throw new IndexOutOfRangeException("Routed UI command with name " + routedCommandName + " is already registered");
}
@ -75,16 +108,17 @@ namespace ICSharpCode.Core.Presentation @@ -75,16 +108,17 @@ namespace ICSharpCode.Core.Presentation
}
/// <summary>
/// Register several input bindings with the same
/// Register input binding in context
///
/// Registering input binding means that when provided gesture is met in specified
/// context routed command will be invoked
/// Registering input binding means that when specified gesture is met in specified
/// context routed command is invoked
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Context class instance. If instance is provided this input binding only applies to provided UI element</param>
/// <param name="routedCommandName">Routed UI command invoked on gesture run</param>
/// <param name="gesture">Gesture</param>
public static void RegisterInputBinding(string contextName, string routedCommandName, InputGesture gesture) {
var inputBindingInfo = new InputBindingInfo(contextName, routedCommandName, gesture);
public static void RegisterInputBinding(string contextName, UIElement contextInstance, string routedCommandName, InputGesture gesture) {
var inputBindingInfo = new InputBindingInfo(contextName, contextInstance, routedCommandName, gesture);
inputBidnings.Add(inputBindingInfo);
}
@ -94,11 +128,13 @@ namespace ICSharpCode.Core.Presentation @@ -94,11 +128,13 @@ namespace ICSharpCode.Core.Presentation
/// 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>
/// <param name="gesture">Gesture</param>
public static void UnregisterInputBindings(string contextName, string routedCommandName, InputGesture gesture) {
public static void UnregisterInputBindings(string contextName, UIElement contextInstance, string routedCommandName, InputGesture gesture) {
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)
&& (gesture == null || inputBidnings[i].Gesture == gesture)) {
inputBidnings.RemoveAt(i);
@ -110,25 +146,40 @@ namespace ICSharpCode.Core.Presentation @@ -110,25 +146,40 @@ namespace ICSharpCode.Core.Presentation
/// Register delegate which will be invoked on change in input bindings in specified context
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Register update handler which will trigger only if input bindings registered for this object where triggered</param>
/// <param name="handler">Update handler delegate</param>
public static void RegisterInputBindingUpdateHandler(string contextName, BindingsUpdatedHandler handler) {
public static void RegisterInputBindingUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) {
if(contextInstance == null) {
contextInstance = NullUIElement;
}
if(!inputBindingsUpdateHandlers.ContainsKey(contextName)) {
inputBindingsUpdateHandlers.Add(contextName, new List<WeakReference>());
inputBindingsUpdateHandlers.Add(contextName, new Dictionary<UIElement, List<BindingsUpdatedHandler>>());
}
inputBindingsUpdateHandlers[contextName].Add(new WeakReference(handler));
if(!inputBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) {
inputBindingsUpdateHandlers[contextName].Add(contextInstance, new List<BindingsUpdatedHandler>());
}
inputBindingsUpdateHandlers[contextName][contextInstance].Add(handler);
}
/// <summary>
/// Remove input bindings update handler
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Unregister update handler which was triggered only if input bindings registered for specific instance where updated</param>
/// <param name="handler">Update handler delegate</param>
public static void UnregisterInputBindingUpdateHandler(string contextName, BindingsUpdatedHandler handler) {
public static void UnregisterInputBindingUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) {
if(contextInstance == null) {
contextInstance = NullUIElement;
}
if(!inputBindingsUpdateHandlers.ContainsKey(contextName)) {
for(int i = inputBindingsUpdateHandlers[contextName].Count - 1; i >= 0; i++) {
if(inputBindingsUpdateHandlers[contextName][i].Target == handler) {
inputBindingsUpdateHandlers[contextName].RemoveAt(i);
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);
}
}
}
}
@ -139,20 +190,36 @@ namespace ICSharpCode.Core.Presentation @@ -139,20 +190,36 @@ namespace ICSharpCode.Core.Presentation
/// Invoke registered input bindings update handlers registered in specified context
/// </summary>
/// <param name="contextName">Context class full name</param>
public static void InvokeInputBindingUpdateHandlers(string contextName) {
public static void InvokeInputBindingUpdateHandlers(string contextName, UIElement contextInstance) {
if(contextInstance == null) {
contextInstance = NullUIElement;
}
if(contextName != null) {
if(inputBindingsUpdateHandlers.ContainsKey(contextName)) {
foreach(var handler in inputBindingsUpdateHandlers[contextName]) {
if(handler != null && handler.Target != null) {
((BindingsUpdatedHandler)handler.Target).Invoke();
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();
}
}
}
} else {
foreach(var contextHandlers in inputBindingsUpdateHandlers) {
foreach(var handler in contextHandlers.Value) {
if(handler != null && handler.Target != null) {
((BindingsUpdatedHandler)handler.Target).Invoke();
foreach(var instanceHandlers in contextHandlers.Value) {
foreach(var handler in instanceHandlers.Value) {
if(handler != null) {
((BindingsUpdatedHandler)handler).Invoke();
}
}
}
}
@ -178,12 +245,26 @@ namespace ICSharpCode.Core.Presentation @@ -178,12 +245,26 @@ namespace ICSharpCode.Core.Presentation
/// in specified context event is routed to specified command (implementing ICommand class)
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Register update handler which is triggered only if input bindings registered for specific instance are updated</param>
/// <param name="routedCommandName">Routed UI command name</param>
/// <param name="className">Command full name to which invokation event is routed</param>
/// <param name="addIn">Add-in in which hosts the command</param>
/// <param name="isLazy">Load add-in referenced assemblies on command invocation</param>
public static void RegisterCommandBinding(string contextName, string routedCommandName, string className, AddIn addIn, bool isLazy) {
var commandBindingInfo = new CommandBindingInfo(contextName, routedCommandName, className, addIn, isLazy);
public static void RegisterCommandBinding(string contextName, UIElement contextInstance, string routedCommandName, string className, AddIn addIn, bool isLazy) {
var commandBindingInfo = new CommandBindingInfo(contextName, contextInstance, routedCommandName, className, addIn, isLazy);
commandBindings.Add(commandBindingInfo);
}
/// <summary>
/// Register command binding which when triggered provided delegates are invoked
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Register update handler which is triggered only if input bindings registered for specific instance are updated</param>
/// <param name="routedCommandName">Routed UI command name</param>
/// <param name="executedEventHandler">Delegate which is called when binding is triggered</param>
/// <param name="canExecuteEventHandler">Delegate which is called to check whether executedEventHandler can be invoked</param>
public static void RegisterCommandBinding(string contextName, UIElement contextInstance, string routedCommandName, ExecutedRoutedEventHandler executedEventHandler, CanExecuteRoutedEventHandler canExecuteEventHandler) {
var commandBindingInfo = new CommandBindingInfo(contextName, contextInstance, routedCommandName, executedEventHandler, canExecuteEventHandler);
commandBindings.Add(commandBindingInfo);
}
@ -193,11 +274,13 @@ namespace ICSharpCode.Core.Presentation @@ -193,11 +274,13 @@ namespace ICSharpCode.Core.Presentation
/// Null arguments are ignored
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Unregister update handler which was triggered only if command bindings registered for specific instance where updated</param>
/// <param name="routedCommandName">Routed UI command name</param>
/// <param name="className">Command full name to which invokation event is routed</param>
public static void UnregisterCommandBindings(string contextName, string routedCommandName, string className) {
public static void UnregisterCommandBindings(string contextName, UIElement contextInstance, string routedCommandName, string className) {
for(int i = commandBindings.Count - 1; i >= 0; i--) {
if((contextName == null || commandBindings[i].ContextName == contextName)
&& (contextInstance == null || commandBindings[i].Context == null || commandBindings[i].Context == contextInstance)
&& (routedCommandName == null || commandBindings[i].RoutedCommandName == routedCommandName)
&& (className == null || commandBindings[i].ClassName == className)) {
inputBidnings.RemoveAt(i);
@ -209,25 +292,39 @@ namespace ICSharpCode.Core.Presentation @@ -209,25 +292,39 @@ namespace ICSharpCode.Core.Presentation
/// Register delegate which will be invoked on any chage in command bindings of specified context
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Register update handler which is triggered only if input bindings registered for specific instance are updated</param>
/// <param name="handler">Update handler delegate</param>
public static void RegisterCommandBindingsUpdateHandler(string contextName, BindingsUpdatedHandler handler) {
public static void RegisterCommandBindingsUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) {
if(contextInstance == null) {
contextInstance = NullUIElement;
}
if(!commandBindingsUpdateHandlers.ContainsKey(contextName)) {
commandBindingsUpdateHandlers.Add(contextName, new List<WeakReference>());
commandBindingsUpdateHandlers.Add(contextName, new Dictionary<UIElement, List<BindingsUpdatedHandler>>());
}
if(!commandBindingsUpdateHandlers[contextName].ContainsKey(contextInstance)) {
commandBindingsUpdateHandlers[contextName].Add(contextInstance, new List<BindingsUpdatedHandler>());
}
commandBindingsUpdateHandlers[contextName].Add(new WeakReference(handler));
commandBindingsUpdateHandlers[contextName][contextInstance].Add(handler);
}
/// <summary>
/// Remove handler command bindings update handler
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Unregister update handler which was triggered only if input bindings registered for specific instance were updated</param>
/// <param name="handler">Update handler delegate</param>
public static void UnregisterCommandBindingsUpdateHandler(string contextName, BindingsUpdatedHandler handler) {
public static void UnregisterCommandBindingsUpdateHandler(string contextName, UIElement contextInstance, BindingsUpdatedHandler handler) {
if(contextInstance == null) {
contextInstance = NullUIElement;
}
if(commandBindingsUpdateHandlers.ContainsKey(contextName)) {
for(int i = commandBindingsUpdateHandlers[contextName].Count - 1; i >= 0; i--) {
if(commandBindingsUpdateHandlers[contextName][i].Target == handler) {
commandBindingsUpdateHandlers[contextName].RemoveAt(i);
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);
}
}
}
}
@ -237,20 +334,37 @@ namespace ICSharpCode.Core.Presentation @@ -237,20 +334,37 @@ namespace ICSharpCode.Core.Presentation
/// Invoke registered command bindings update handlers registered in specified context
/// </summary>
/// <param name="contextName">Context class full name</param>
public static void InvokeCommandBindingUpdateHandlers(string contextName) {
/// <param name="contextInstance">Invoke update handlers which handle update only in specifyc context</param>
public static void InvokeCommandBindingUpdateHandlers(string contextName, UIElement contextInstance) {
if(contextInstance == null) {
contextInstance = NullUIElement;
}
if(contextName != null) {
if(commandBindingsUpdateHandlers.ContainsKey(contextName)) {
foreach(var handler in commandBindingsUpdateHandlers[contextName]) {
if(handler != null && handler.Target != null) {
((BindingsUpdatedHandler)handler.Target).Invoke();
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();
}
}
}
}
} else {
foreach(var contextHandlers in commandBindingsUpdateHandlers) {
foreach(var handler in contextHandlers.Value) {
if(handler != null && handler.Target != null) {
((BindingsUpdatedHandler)handler.Target).Invoke();
foreach(var instanceHandlers in contextHandlers.Value) {
foreach(var handler in instanceHandlers.Value) {
if(handler != null) {
((BindingsUpdatedHandler)handler).Invoke();
}
}
}
}
@ -305,7 +419,6 @@ namespace ICSharpCode.Core.Presentation @@ -305,7 +419,6 @@ namespace ICSharpCode.Core.Presentation
}
}
/// <summary>
/// Load context
/// </summary>
@ -322,22 +435,22 @@ namespace ICSharpCode.Core.Presentation @@ -322,22 +435,22 @@ namespace ICSharpCode.Core.Presentation
/// Null arguments are ignored
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Get command bindings assigned only to specific context</param>
/// <param name="routedCommandName">Context class full name</param>
/// <param name="className">Context class full name</param>
/// <returns>Collection of managed command bindings</returns>
public static CommandBindingCollection GetCommandBindings(string contextName, string routedCommandName, string className) {
public static CommandBindingCollection GetCommandBindings(string contextName, UIElement contextInstance, string routedCommandName, string className) {
var bindings = new CommandBindingCollection();
foreach(var binding in commandBindings) {
if((contextName == null || binding.ContextName == contextName)
&& (contextInstance == null || binding.Context == null || binding.Context == contextInstance)
&& (routedCommandName == null || binding.RoutedCommandName == routedCommandName)
&& (className == null || binding.ClassName == className)) {
var handlers = new CommandBindingHandlersContainer(binding);
var managedCommandBinding = new ManagedCommandBinding(binding.RoutedCommand);
managedCommandBinding.CanExecute += handlers.CanExecuteHandler;
managedCommandBinding.Executed += handlers.ExecutedHanler;
managedCommandBinding.CanExecute += binding.CanExecuteEventHandler;
managedCommandBinding.Executed += binding.ExecutedEventHandler;
bindings.Add(managedCommandBinding);
}
@ -352,13 +465,15 @@ namespace ICSharpCode.Core.Presentation @@ -352,13 +465,15 @@ namespace ICSharpCode.Core.Presentation
/// Null arguments are ignored
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Get input bindings assigned only to specific context</param>
/// <param name="routedCommandName">Routed UI command name</param>
/// <param name="gesture">Gesture</param>
public static InputBindingCollection GetInputBindings(string contextName, string routedCommandName, InputGesture gesture) {
public static InputBindingCollection GetInputBindings(string contextName, UIElement contextInstance, string routedCommandName, InputGesture gesture) {
var bindings = new InputBindingCollection();
foreach(var binding in inputBidnings) {
if((contextName == null || binding.ContextName == contextName)
&& (contextInstance == null || binding.Context == null || binding.Context == contextInstance)
&& (routedCommandName == null || binding.RoutedCommandName == routedCommandName)
&& (gesture == null || binding.Gesture == gesture)) {
@ -375,10 +490,11 @@ namespace ICSharpCode.Core.Presentation @@ -375,10 +490,11 @@ namespace ICSharpCode.Core.Presentation
/// Null arguments are ignored
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="contextInstance">Get gestures assigned only to specific context</param>
/// <param name="routedCommandName">Routed UI command name</param>
/// <param name="gesture">Gesture</param>
public static InputGestureCollection GetInputGestures(string contextName, string routedCommandName, InputGesture gesture) {
var bindings = GetInputBindings(contextName, routedCommandName, gesture);
public static InputGestureCollection GetInputGestures(string contextName, UIElement contextInstance, string routedCommandName, InputGesture gesture) {
var bindings = GetInputBindings(contextName, contextInstance, routedCommandName, gesture);
var gestures = new InputGestureCollection();
foreach(InputBinding binding in bindings) {
@ -389,51 +505,63 @@ namespace ICSharpCode.Core.Presentation @@ -389,51 +505,63 @@ namespace ICSharpCode.Core.Presentation
}
/// <summary>
/// Stores Executed and CanExecute event handlers used in command bindings
/// Create default BindingUpdateHandler which will update command bindings in specified context
/// </summary>
class CommandBindingHandlersContainer
{
private CommandBindingInfo binding;
/// <param name="bindingsCollection">Collection which should be updated with latest bindings</param>
/// <param name="contextName">Context name which was used to register command bindings</param>
/// <param name="contextInstance">Reference to instance which is used to find command bindings registered in specific context instance</param>
/// <returns>Bindings updated handler</returns>
public static BindingsUpdatedHandler CreateCommandBindingUpdateHandler(CommandBindingCollection bindingsCollection, string contextName, UIElement contextInstance) {
return new CommonCommandBindingUpdateDelegate(bindingsCollection, contextName, contextInstance).UpdateCommandBinding;
}
/// <summary>
/// Constructor
/// Create default BindingUpdateHandler which will update input bindings in specified context
/// </summary>
/// <param name="binding">Reference to object holding command bining details</param>
public CommandBindingHandlersContainer(CommandBindingInfo binding) {
this.binding = binding;
/// <param name="bindingsCollection">Collection which should be updated with latest bindings</param>
/// <param name="contextName">Context name which was used to register input bindings</param>
/// <param name="contextInstance">Reference to instance which is used to find command bindings registered in specific context instance</param>
/// <returns>Bindings updated handler</returns>
public static BindingsUpdatedHandler CreateInputBindingUpdateHandler(InputBindingCollection bindingsCollection, string contextName, UIElement contextInstance) {
return new CommonInputBindingUpdateDelegate(bindingsCollection, contextName, contextInstance).UpdateInputBinding;
}
/// <summary>
/// CanExecute event handler
/// </summary>
/// <param name="sender">Object which raised this event</param>
/// <param name="e">Event arguments</param>
public void CanExecuteHandler(Object sender, CanExecuteRoutedEventArgs e) {
if(binding.IsLazy && binding.Class == null) {
e.CanExecute = true;
} else if(binding.Class == null) {
e.CanExecute = false;
} else {
e.CanExecute = binding.Class.CanExecute(e.Parameter);
class CommonCommandBindingUpdateDelegate
{
CommandBindingCollection bindingsCollection;
string contextName;
UIElement contextInstance;
public CommonCommandBindingUpdateDelegate(CommandBindingCollection bindingsCollection, string contextName, UIElement contextInstance) {
this.bindingsCollection = bindingsCollection;
this.contextName = contextName;
this.contextInstance = contextInstance;
}
public void UpdateCommandBinding() {
var newBindings = CommandsRegistry.GetCommandBindings(contextName, contextInstance, null, null);
CommandsRegistry.RemoveManagedCommandBindings(bindingsCollection);
bindingsCollection.AddRange(newBindings);
}
}
/// <summary>
/// Executed event handler
/// </summary>
/// <param name="sender">Object which raised this event</param>
/// <param name="e">Event arguments</param>
public void ExecutedHanler(Object sender, ExecutedRoutedEventArgs e) {
if(binding.IsLazy && binding.Class == null) {
binding.AddIn.LoadRuntimeAssemblies();
var command = (ICommand)binding.AddIn.CreateObject(binding.ClassName);
CommandsRegistry.LoadCommand(binding.ClassName, command);
}
class CommonInputBindingUpdateDelegate
{
InputBindingCollection bindingsCollection;
string contextName;
UIElement contextInstance;
if(binding.Class != null) {
binding.Class.Execute(e.Parameter);
public CommonInputBindingUpdateDelegate(InputBindingCollection bindingsCollection, string contextName, UIElement contextInstance) {
this.bindingsCollection = bindingsCollection;
this.contextName = contextName;
this.contextInstance = contextInstance;
}
public void UpdateInputBinding() {
var newBindings = CommandsRegistry.GetInputBindings(contextName, contextInstance, null, null);
CommandsRegistry.RemoveManagedInputBindings(bindingsCollection);
bindingsCollection.AddRange(newBindings);
}
}
}

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

@ -11,11 +11,11 @@ namespace ICSharpCode.Core.Presentation @@ -11,11 +11,11 @@ namespace ICSharpCode.Core.Presentation
/// </summary>
public static class CommandsService
{
private static void RegisterRoutedCommands(Type type) {
public static void RegisterRoutedCommands(Type type) {
var typeProperties = type.GetProperties(BindingFlags.Static | BindingFlags.Public);
foreach(var property in typeProperties) {
var command = (RoutedUICommand)property.GetValue(null, null);
CommandsRegistry.RegisterRoutedUICommand(type.Name + "." + command.Name, command.Text);
CommandsRegistry.RegisterRoutedUICommand(command);
}
}
@ -46,13 +46,13 @@ namespace ICSharpCode.Core.Presentation @@ -46,13 +46,13 @@ namespace ICSharpCode.Core.Presentation
CommandsRegistry.RegisterRoutedUICommand(desc.Command, desc.Command);
}
CommandsRegistry.RegisterCommandBinding(contextName, desc.Command, desc.Class, desc.Codon.AddIn, desc.Lazy);
CommandsRegistry.RegisterCommandBinding(contextName, null, desc.Command, desc.Class, desc.Codon.AddIn, desc.Lazy);
// If gestures are provided register input binding in the same context
if(!string.IsNullOrEmpty(desc.Gestures)) {
var gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromString(desc.Gestures);
foreach(InputGesture gesture in gestures) {
CommandsRegistry.RegisterInputBinding(contextName, desc.Command, gesture);
CommandsRegistry.RegisterInputBinding(contextName, null, desc.Command, gesture);
}
}
}
@ -65,7 +65,7 @@ namespace ICSharpCode.Core.Presentation @@ -65,7 +65,7 @@ namespace ICSharpCode.Core.Presentation
var contextName = !string.IsNullOrEmpty(desc.Context) ? desc.Context : CommandsRegistry.DefaultContext;
var gesture = (KeyGesture)new KeyGestureConverter().ConvertFromInvariantString(desc.Gesture);
CommandsRegistry.RegisterInputBinding(contextName, desc.Command, gesture);
CommandsRegistry.RegisterInputBinding(contextName, null, desc.Command, gesture);
}
}
}

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

@ -9,6 +9,8 @@ namespace ICSharpCode.Core.Presentation @@ -9,6 +9,8 @@ namespace ICSharpCode.Core.Presentation
/// </summary>
public class InputBindingInfo
{
private UIElement contextInstance;
/// <summary>
/// Constructor
/// </summary>
@ -21,6 +23,14 @@ namespace ICSharpCode.Core.Presentation @@ -21,6 +23,14 @@ namespace ICSharpCode.Core.Presentation
Gesture = gesture;
}
public InputBindingInfo(string contextName, UIElement contextInstance, string routedCommandName, InputGesture gesture) {
ContextName = contextName;
RoutedCommandName = routedCommandName;
Gesture = gesture;
this.contextInstance = contextInstance;
}
/// <summary>
/// Context class full name
///
@ -37,12 +47,16 @@ namespace ICSharpCode.Core.Presentation @@ -37,12 +47,16 @@ namespace ICSharpCode.Core.Presentation
/// </summary>
public UIElement Context {
get {
if(contextInstance != null) {
return contextInstance;
} else {
UIElement context;
CommandsRegistry.contexts.TryGetValue(ContextName, out context);
return context;
}
}
}
/// <summary>
/// Routed command name

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

@ -127,9 +127,9 @@ namespace ICSharpCode.Core.Presentation @@ -127,9 +127,9 @@ namespace ICSharpCode.Core.Presentation
} else {
this.Command = routedCommand;
var gestures = CommandsRegistry.GetInputGestures(CommandsRegistry.DefaultContext, routedCommand.Name, null);
var gestures = CommandsRegistry.GetInputGestures(CommandsRegistry.DefaultContext, null, routedCommand.Name, null);
var gesturesString = (string)new InputGestureCollectionConverter().ConvertToInvariantString(gestures);
this.InputGestureText = "M: " + gesturesString;
this.InputGestureText = gesturesString;
}
} else {
this.Command = CommandWrapper.GetCommand(codon, caller, createCommand);

Loading…
Cancel
Save