Browse Source

Missing files from initial commands registry implementation

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4128 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts^2
Sergej Andrejev 17 years ago
parent
commit
3f16aa470a
  1. 68
      src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDescriptor.cs
  2. 50
      src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDescriptor.cs
  3. 118
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandBindingInfo.cs
  4. 326
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsRegistry.cs
  5. 35
      src/Main/ICSharpCode.Core.Presentation/CommandsService/ManagedCommandBinding.cs
  6. 29
      src/Main/ICSharpCode.Core.Presentation/CommandsService/ManagedInputBinding.cs

68
src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDescriptor.cs

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
using System;
namespace ICSharpCode.Core
{
/// <summary>
/// Stores information about command binding loaded from add-in tree
/// </summary>
public class CommandBindingDescriptor
{
/// <summary>
/// Codon used to create this descriptor
/// </summary>
public Codon Codon {
get; private set;
}
/// <summary>
/// Full name of the command class which will be executed when this
/// binding is triggered
/// </summary>
public string Class {
get {
return Codon.Properties["class"];
}
}
/// <summary>
/// Full name of routed UI command which will trigger this binding
/// </summary>
public string Command {
get {
return Codon.Properties["command"];
}
}
/// <summary>
/// Full name of context class.
///
/// UI element in which this binding will be valid
/// </summary>
public string Context {
get {
return Codon.Properties["context"];
}
}
/// <summary>
/// Lazy loading
///
/// If true add-in referenced assemblies are loaded when command is invoked.
/// Otherwise command can't be invoked until addin is loaded
/// </summary>
public bool Lazy {
get {
return Codon.Properties["lazy"] == "1" || Codon.Properties["lazy"] == "true";
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="codon">Reference to codon used to create this descriptor</param>
public CommandBindingDescriptor(Codon codon)
{
Codon = codon;
}
}
}

50
src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDescriptor.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
using System;
namespace ICSharpCode.Core
{
/// <summary>
/// Stores information about input binding loaded from add-in tree
/// </summary>
public class InputBindingDescriptor
{
private Codon codon;
/// <summary>
/// Full name of routed UI command which will be invoked when this binding is triggered
/// </summary>
public string Command {
get {
return codon.Properties["command"];
}
}
/// <summary>
/// Full name of context class.
///
/// UI element in which this binding will be valid
/// </summary>
public string Context {
get {
return codon.Properties["context"];
}
}
/// <summary>
/// Description of gesture which will trigger this bindin
/// </summary>
public string Gesture {
get {
return codon.Properties["gesture"];
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="codon">Reference to codon used to create this descriptor</param>
public InputBindingDescriptor(Codon codon)
{
this.codon = codon;
}
}
}

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

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
using System;
using System.Windows;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Stores details about command binding
/// </summary>
public class CommandBindingInfo
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="contextName">Context full name</param>
/// <param name="routedCommandName">Name of routed UI command which triggers this binding</param>
/// <param name="className">Command full name</param>
/// <param name="addIn">Add-in where command is registered</param>
/// <param name="isLazy">Lazy load command</param>
public CommandBindingInfo(string contextName, string routedCommandName, string className, AddIn addIn, bool isLazy) {
RoutedCommandName = routedCommandName;
ContextName = contextName;
ClassName = className;
IsLazy = isLazy;
AddIn = addIn;
}
/// <summary>
/// Routed command name
///
/// Described binding is triggered by this routed command
/// </summary>
/// <seealso cref="RoutedCommand"></seealso>
public string RoutedCommandName {
get; private set;
}
/// <summary>
/// Routed command instance
///
/// Described binding is triggered by this routed command
/// </summary>
/// <seealso cref="RoutedCommandName"></seealso>
public RoutedUICommand RoutedCommand {
get {
return CommandsRegistry.GetRoutedUICommand(RoutedCommandName);
}
}
/// <summary>
/// Add-in to which binded command belongs
/// </summary>
public AddIn AddIn {
get; private set;
}
/// <summary>
/// Binded command full name
///
/// This command is invoke when this binding is triggered
/// </summary>
/// <seealso cref="Class"></seealso>
public string ClassName {
get; private set;
}
/// <summary>
/// Binded command instance
///
/// This command is invoke when this binding is triggered. If this value is equal
/// to null then add-in is not loaded yet, see <see cref="IsLazy">IsLazy</see> attribute
/// for details
/// </summary>
/// <seealso cref="ClassName"></seealso>
public System.Windows.Input.ICommand Class {
get {
System.Windows.Input.ICommand command;
CommandsRegistry.commands.TryGetValue(ClassName, out command);
return command;
}
}
/// <summary>
/// Context class full name
///
/// Described binding will be valid in this context
/// </summary>
public string ContextName{
get; private set;
}
/// <summary>
/// Context class instance
///
/// Described binding will be valid in this context
/// </summary>
public UIElement Context {
get {
UIElement context;
CommandsRegistry.contexts.TryGetValue(ContextName, out context);
return context;
}
}
/// <summary>
/// Lazy load
///
/// If lazy load is enabled then all add-in references are loaded when this
/// command is invoked. Otherwice if add-in is not loaded and IsLazy is set
/// to false then this binding can't be triggered until add-in is loaded.
/// </summary>
public bool IsLazy{
get; private set;
}
}
}

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

@ -0,0 +1,326 @@ @@ -0,0 +1,326 @@
using System;
using System.Collections.Generic;
using System.Windows.Input;
using System.Windows;
using ICSharpCode.Core;
using System.Threading;
namespace ICSharpCode.Core.Presentation
{
public delegate void BindingsUpdatedHandler();
/// <summary>
/// Global registry to store and access commands, command bindings and input bindings
/// </summary>
public static class CommandsRegistry
{
/// <summary>
/// Default application context.
///
/// This should be set to the root UI element
/// </summary>
public static string DefaultContext {
get; set;
}
private static List<CommandBindingInfo> commandBindings = new List<CommandBindingInfo>();
private static List<InputBindingInfo> inputBidnings = new List<InputBindingInfo>();
private static Dictionary<string, RoutedUICommand> routedCommands = new Dictionary<string, RoutedUICommand>();
internal static Dictionary<string, System.Windows.Input.ICommand> commands = new Dictionary<string, System.Windows.Input.ICommand>();
internal static Dictionary<string, UIElement> contexts = new Dictionary<string, UIElement>();
private static Dictionary<string, List<BindingsUpdatedHandler>> commandBindingsUpdateHandlers = new Dictionary<string, List<BindingsUpdatedHandler>>();
private static Dictionary<string, List<BindingsUpdatedHandler>> inputBindingsUpdateHandlers = new Dictionary<string, List<BindingsUpdatedHandler>>();
/// <summary>
/// Get reference to routed UI command by name
/// </summary>
/// <param name="routedCommandName">Routed command name</param>
/// <returns>Routed command instance</returns>
public static RoutedUICommand GetRoutedUICommand(string routedCommandName) {
RoutedUICommand routedUICommand;
routedCommands.TryGetValue(routedCommandName, out routedUICommand);
return routedUICommand;
}
/// <summary>
/// Register new routed command in the global registry
///
/// Routed command name should be uniq in SharpDevelop scope.
/// Use "." to emulate namespaces
/// </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));
if(!routedCommands.ContainsKey(routedCommandName)) {
routedCommands.Add(routedCommandName, routedCommand);
} else {
throw new IndexOutOfRangeException("Routed command with name " + routedCommandName + " is already registered");
}
}
/// <summary>
/// Remove routed command from global registry
/// </summary>
/// <param name="routedCommandName">Routed command name</param>
public static void UnregisterRoutedUICommand(string routedCommandName) {
if(routedCommands.ContainsKey(routedCommandName)) {
routedCommands.Remove(routedCommandName);
}
}
/// <summary>
/// Register input binding
///
/// Registering input binding means that when provided gesture is met in specified
/// context routed command will be invoked
/// </summary>
/// <param name="contextName">Context class full name</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, KeyGesture gesture) {
var inputBindingInfo = new InputBindingInfo(contextName, routedCommandName, gesture);
inputBidnings.Add(inputBindingInfo);
}
/// <summary>
/// Remove input binding from global registry
///
/// Null attributes are ignored and oly bindings which satisfy not null arguments are removed
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="routedCommandName">Routed UI command name</param>
/// <param name="gesture">Gesture</param>
public static void UnregisterInputBindings(string contextName, string routedCommandName, KeyGesture gesture) {
for(var i = inputBidnings.Count - 1; i >= 0; i--) {
if((contextName == null || inputBidnings[i].ContextName == contextName)
&& (routedCommandName == null || inputBidnings[i].RoutedCommandName == routedCommandName)
&& (gesture == null || inputBidnings[i].Gesture == gesture)) {
inputBidnings.RemoveAt(i);
}
}
}
/// <summary>
/// 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="handler">Update handler delegate</param>
public static void RegisterInputBindingUpdateHandler(string contextName, BindingsUpdatedHandler handler) {
if(!inputBindingsUpdateHandlers.ContainsKey(contextName)) {
inputBindingsUpdateHandlers.Add(contextName, new List<BindingsUpdatedHandler>());
}
inputBindingsUpdateHandlers[contextName].Add(handler);
}
/// <summary>
/// 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) {
if(contextName != null) {
if(inputBindingsUpdateHandlers.ContainsKey(contextName)) {
foreach(var handler in inputBindingsUpdateHandlers[contextName]) {
handler.Invoke();
}
}
} else {
foreach(var contextHandlers in inputBindingsUpdateHandlers) {
foreach(var handler in contextHandlers.Value) {
handler.Invoke();
}
}
}
}
/// <summary>
/// Remove all managed input bindings from input bindings collection
/// </summary>
/// <param name="inputBindingCollection"></param>
public static void RemoveManagedInputBindings(InputBindingCollection inputBindingCollection) {
for(var i = inputBindingCollection.Count - 1; i >= 0; i--) {
if(inputBindingCollection[i] is ManagedInputBinding) {
inputBindingCollection.RemoveAt(i);
}
}
}
/// <summary>
/// Register command binding
///
/// Registering command binding means that when provided routed command is invoked
/// in specified context event is routed to specified command (implementing ICommand class)
/// </summary>
/// <param name="contextName">Context class full name</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);
commandBindings.Add(commandBindingInfo);
}
/// <summary>
/// Remove registered command bindnig from global registry
/// </summary>
/// <param name="contextName"></param>
/// <param name="routedCommandName"></param>
/// <param name="className"></param>
public static void UnregisterCommandBindings(string contextName, string routedCommandName, string className) {
for(var i = commandBindings.Count - 1; i >= 0; i--) {
if((contextName == null || commandBindings[i].ContextName == contextName)
&& (routedCommandName == null || commandBindings[i].RoutedCommandName == routedCommandName)
&& (className == null || commandBindings[i].ClassName == className)) {
inputBidnings.RemoveAt(i);
}
}
}
/// <summary>
/// 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="handler">Update handler delegate</param>
public static void RegisterCommandBindingsUpdateHandler(string contextName, BindingsUpdatedHandler handler) {
if(!commandBindingsUpdateHandlers.ContainsKey(contextName)) {
commandBindingsUpdateHandlers.Add(contextName, new List<BindingsUpdatedHandler>());
}
commandBindingsUpdateHandlers[contextName].Add(handler);
}
/// <summary>
/// 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) {
if(contextName != null) {
if(commandBindingsUpdateHandlers.ContainsKey(contextName)) {
foreach(var handler in commandBindingsUpdateHandlers[contextName]) {
handler.Invoke();
}
}
} else {
foreach(var contextHandlers in commandBindingsUpdateHandlers) {
foreach(var handler in contextHandlers.Value) {
handler.Invoke();
}
}
}
}
/// <summary>
/// Remove all managed command bindungs from command bindings collection
/// </summary>
/// <param name="commandBindingsCollection"></param>
public static void RemoveManagedCommandBindings(CommandBindingCollection commandBindingsCollection) {
for(var i = commandBindingsCollection.Count - 1; i >= 0; i--) {
if(commandBindingsCollection[i] is ManagedCommandBinding) {
commandBindingsCollection.RemoveAt(i);
}
}
}
/// <summary>
/// Load all registered commands in addin
/// </summary>
/// <param name="addIn">Addin</param>
public static void LoadAddinCommands(AddIn addIn) {
foreach(var binding in commandBindings) {
if(binding.AddIn != addIn) continue;
LoadCommand(binding.ClassName, addIn.CreateObject(binding.ClassName));
}
}
/// <summary>
/// Load command
/// </summary>
/// <param name="commandName">Command name</param>
/// <param name="command">Command instance</param>
public static void LoadCommand(string commandName, object command) {
var wpfCommand = command as System.Windows.Input.ICommand;
if(wpfCommand == null) {
wpfCommand = new WpfCommandWrapper((ICSharpCode.Core.ICommand)command);
}
commands.Add(commandName, wpfCommand);
}
/// <summary>
/// Load context
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <param name="context">Context class instance</param>
public static void LoadContext(string contextName, UIElement context) {
contexts[contextName] = context;
}
/// <summary>
/// Get all commands bindings registered in provided context
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <returns>Collection of managed command bindings</returns>
public static CommandBindingCollection GetCommandBindings(string contextName) {
var bindings = new CommandBindingCollection();
foreach(var binding in commandBindings) {
if(binding.ContextName != contextName) continue;
var managedCommandBinding = new ManagedCommandBinding(binding.RoutedCommand);
managedCommandBinding.CanExecute += delegate(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);
}
};
managedCommandBinding.Executed += delegate(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);
}
if(binding.Class != null) {
binding.Class.Execute(e.Parameter);
}
};
bindings.Add(managedCommandBinding);
}
return bindings;
}
/// <summary>
/// Get list of all input bindings registered in provided context
/// </summary>
/// <param name="contextName">Context class full name</param>
/// <returns>Collection of managed command bindings</returns>
public static InputBindingCollection GetInputBindings(string contextName) {
var bindings = new InputBindingCollection();
foreach(var binding in inputBidnings) {
if(binding.ContextName != contextName) continue;
bindings.Add(new ManagedInputBinding(binding.RoutedCommand, binding.Gesture));
}
return bindings;
}
}
}

35
src/Main/ICSharpCode.Core.Presentation/CommandsService/ManagedCommandBinding.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
using System;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// ManagedCommandBinding is used to distinguish command bindings managed
/// by CommandsRegistry from other command bindings not managed by CommandsRegistry
///
/// If command binding is not managed then CommandsRegistry ignores it when
/// performing any action
/// </summary>
public class ManagedCommandBinding : System.Windows.Input.CommandBinding
{
/// <see cref="System.Windows.Input.CommandBinding()" />
public ManagedCommandBinding()
: base()
{ }
/// <see cref="System.Windows.Input.CommandBinding(System.Windows.Input.ICommand)" />
public ManagedCommandBinding(System.Windows.Input.ICommand command)
: base(command)
{ }
/// <see cref="System.Windows.Input.CommandBinding(System.Windows.Input.ICommand, System.Windows.Input.ExecutedRoutedEventHandler)" />
public ManagedCommandBinding(System.Windows.Input.ICommand command, System.Windows.Input.ExecutedRoutedEventHandler executed)
: base(command, executed)
{ }
/// <see cref="System.Windows.Input.CommandBinding(System.Windows.Input.ICommand, System.Windows.Input.ExecutedRoutedEventHandler, System.Windows.Input.CanExecuteRoutedEventHandler)" />
public ManagedCommandBinding(System.Windows.Input.ICommand command, System.Windows.Input.ExecutedRoutedEventHandler executed, System.Windows.Input.CanExecuteRoutedEventHandler canExecute)
: base(command, executed, canExecute)
{ }
}
}

29
src/Main/ICSharpCode.Core.Presentation/CommandsService/ManagedInputBinding.cs

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
using System;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// ManagedInputBinding is used to distinguish input bindings managed
/// by CommandsRegistry from other input bindings not managed by CommandsRegistry.
///
/// If input binding is not managed then CommansRegistry ignores it when
/// performing any action
/// </summary>
public class ManagedInputBinding : System.Windows.Input.KeyBinding
{
/// <see cref="System.Windows.Input.InputBinding()"></see>
public ManagedInputBinding() : base()
{ }
/// <see cref="System.Windows.Input.InputBinding(System.Windows.Input.ICommand, System.Windows.Input.KeyGesture)"></see>
public ManagedInputBinding(System.Windows.Input.ICommand command, System.Windows.Input.KeyGesture gesture)
: base(command, gesture)
{ }
/// <see cref="System.Windows.Input.InputBinding(System.Windows.Input.ICommand, System.Windows.Input.Key, System.Windows.Input.ModifierKeys)"></see>
public ManagedInputBinding(System.Windows.Input.ICommand command, System.Windows.Input.Key key, System.Windows.Input.ModifierKeys modifiers)
: base(command, key, modifiers)
{ }
}
}
Loading…
Cancel
Save