Browse Source

Initial commands registry implementation

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4127 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts^2
Sergej Andrejev 16 years ago
parent
commit
8660b4da03
  1. 19
      AddIns/ICSharpCode.SharpDevelop.addin
  2. 17
      src/Main/Base/Project/Src/Commands/ToolsCommands.cs
  3. 19
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonPadContent.cs
  4. 18
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
  5. 24
      src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs
  6. 7
      src/Main/Core/Project/ICSharpCode.Core.csproj
  7. 25
      src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDoozer.cs
  8. 25
      src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDoozer.cs
  9. 39
      src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/RoutedUICommandDescriptor.cs
  10. 25
      src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/RoutedUICommandDoozer.cs
  11. 3
      src/Main/Core/Project/Src/AddInTree/AddInTree.cs
  12. 42
      src/Main/ICSharpCode.Core.Presentation/CommandsService/CommandsService.cs
  13. 76
      src/Main/ICSharpCode.Core.Presentation/CommandsService/InputBindingInfo.cs
  14. 41
      src/Main/ICSharpCode.Core.Presentation/CommandsService/WpfCommandWrapper.cs
  15. 9
      src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
  16. 4
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs

19
AddIns/ICSharpCode.SharpDevelop.addin

@ -51,6 +51,25 @@ @@ -51,6 +51,25 @@
<Import assembly=":ICSharpCode.TextEditor"/>
</Runtime>
<!-- Commands registry test -->
<Path name="/SharpDevelop/Workbench/RoutedUICommands">
<RoutedUICommand id="SharpDevelop.CreateNewFile" text="Create new file" />
</Path>
<Path name="/SharpDevelop/Workbench/CommandBindings">
<CommandBinding id="CreateNewFile"
command="SharpDevelop.CreateNewFile"
class="ICSharpCode.SharpDevelop.Commands.TestCommand"
lazy="true" />
</Path>
<Path name="/SharpDevelop/Workbench/InputBindings">
<InputBinding id="CreateNewFile1"
command="SharpDevelop.CreateNewFile"
gesture="Ctrl+M" />
</Path>
<!-- Commands registry test -->
<Path name = "/SharpDevelop/Workbench/Ambiences">
<Class id = ".NET"
class = "ICSharpCode.SharpDevelop.NetAmbience"/>

17
src/Main/Base/Project/Src/Commands/ToolsCommands.cs

@ -8,10 +8,27 @@ @@ -8,10 +8,27 @@
using System;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Gui;
using System.Windows.Input;
namespace ICSharpCode.SharpDevelop.Commands
{
public class TestCommand : System.Windows.Input.ICommand
{
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
System.Windows.MessageBox.Show("test");
}
public bool CanExecute(object parameter)
{
return true;
}
}
public class OptionsCommand : AbstractMenuCommand
{
public static bool? ShowTabbedOptions(string dialogTitle, AddInTreeNode node)

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

@ -10,6 +10,7 @@ using System; @@ -10,6 +10,7 @@ using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Windows.Input;
using AvalonDock;
using ICSharpCode.Core;
@ -54,6 +55,24 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -54,6 +55,24 @@ namespace ICSharpCode.SharpDevelop.Gui
if (padInstance != null) {
this.SetContent(padInstance.Control, padInstance);
placeholder = null;
var contextName = padInstance.GetType().FullName;
CommandsRegistry.LoadContext(contextName, (UIElement)Content);
CommandsRegistry.RegisterCommandBindingsUpdateHandler(contextName, delegate {
var bindings = CommandsRegistry.GetCommandBindings(contextName);
CommandsRegistry.RemoveManagedCommandBindings(CommandBindings);
CommandBindings.AddRange(bindings);
});
CommandsRegistry.RegisterInputBindingUpdateHandler(contextName, delegate {
var bindings = CommandsRegistry.GetInputBindings(contextName);
CommandsRegistry.RemoveManagedInputBindings(InputBindings);
InputBindings.AddRange(bindings);
});
CommandsRegistry.InvokeCommandBindingUpdateHandlers(contextName);
CommandsRegistry.InvokeInputBindingUpdateHandlers(contextName);
}
}
}

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

@ -91,6 +91,24 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -91,6 +91,24 @@ namespace ICSharpCode.SharpDevelop.Gui
}
oldActiveViewContent = newActiveViewContent;
CommandManager.InvalidateRequerySuggested();
var contextName = newActiveViewContent.GetType().FullName;
CommandsRegistry.LoadContext(contextName, (UIElement)Content);
CommandsRegistry.RegisterCommandBindingsUpdateHandler(contextName, delegate {
var bindings = CommandsRegistry.GetCommandBindings(contextName);
CommandsRegistry.RemoveManagedCommandBindings(CommandBindings);
CommandBindings.AddRange(bindings);
});
CommandsRegistry.RegisterInputBindingUpdateHandler(contextName, delegate {
var bindings = CommandsRegistry.GetInputBindings(contextName);
CommandsRegistry.RemoveManagedInputBindings(InputBindings);
InputBindings.AddRange(bindings);
});
CommandsRegistry.InvokeCommandBindingUpdateHandlers(contextName);
CommandsRegistry.InvokeInputBindingUpdateHandlers(contextName);
}
sealed class ViewContentCollection : Collection<IViewContent>

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

@ -80,6 +80,30 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -80,6 +80,30 @@ namespace ICSharpCode.SharpDevelop.Gui
}
}
CommandsRegistry.DefaultContext = this.GetType().Name;
// Load all commands and and key bindings from addin tree
CommandsService.RegisterRoutedUICommands(this, "/SharpDevelop/Workbench/RoutedUICommands");
CommandsService.RegisterCommandBindings(this, "/SharpDevelop/Workbench/CommandBindings");
CommandsService.RegisterInputBindings(this, "/SharpDevelop/Workbench/InputBindings");
// 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);
CommandsRegistry.RemoveManagedCommandBindings(CommandBindings);
CommandBindings.AddRange(bindings);
});
CommandsRegistry.RegisterInputBindingUpdateHandler(CommandsRegistry.DefaultContext, delegate {
var bindings = CommandsRegistry.GetInputBindings(CommandsRegistry.DefaultContext);
CommandsRegistry.RemoveManagedInputBindings(InputBindings);
InputBindings.AddRange(bindings);
});
CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContext);
CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContext);
mainMenu.ItemsSource = MenuService.CreateMenuItems(this, this, mainMenuPath);
toolBars = ToolBarService.CreateToolBars(this, "/SharpDevelop/Workbench/ToolBar");

7
src/Main/Core/Project/ICSharpCode.Core.csproj

@ -60,6 +60,12 @@ @@ -60,6 +60,12 @@
<Compile Include="Src\AddInTree\AddIn\Codon.cs" />
<Compile Include="Src\AddInTree\AddIn\ComplexCondition.cs" />
<Compile Include="Src\AddInTree\AddIn\Condition.cs" />
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\Command\CommandBindingDescriptor.cs" />
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\Command\CommandBindingDoozer.cs" />
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\Command\InputBindingDescriptor.cs" />
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\Command\InputBindingDoozer.cs" />
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\Command\RoutedUICommandDescriptor.cs" />
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\Command\RoutedUICommandDoozer.cs" />
<Compile Include="Src\AddInTree\AddIn\ExtensionPath.cs" />
<Compile Include="Src\AddInTree\AddIn\IConditionEvaluator.cs" />
<Compile Include="Src\AddInTree\AddIn\ICondition.cs" />
@ -122,6 +128,7 @@ @@ -122,6 +128,7 @@
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\ToolBarItem\ITextBoxCommand.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Src\AddInTree\AddIn\DefaultDoozers\Command" />
<Folder Include="Src\Services\LoggingService" />
<Folder Include="Src\Services\ResourceService" />
<Content Include="..\..\..\..\data\schemas\AddIn.xsd">

25
src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/CommandBindingDoozer.cs

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
using System;
namespace ICSharpCode.Core
{
/// <summary>
/// Creates descriptor containing information about command binding
/// </summary>
public class CommandBindingDoozer : IDoozer
{
/// <see cref="IDoozer.HandleConditions" />
public bool HandleConditions {
get {
return false;
}
}
/// <see cref="IDoozer.BuildItem(object, Codon, System.Collections.ArrayList)">
/// Builds CommandBindingDescriptor
/// </see>
public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems)
{
return new CommandBindingDescriptor(codon);
}
}
}

25
src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/InputBindingDoozer.cs

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
using System;
namespace ICSharpCode.Core
{
/// <summary>
/// Creates descriptor containing information about input binding
/// </summary>
public class InputBindingDoozer : IDoozer
{
/// <see cref="IDoozer.HandleConditions" />
public bool HandleConditions {
get {
return true;
}
}
/// <see cref="IDoozer.BuildItem(object, Codon, System.Collections.ArrayList)">
/// Builds InputBindingDescriptor
/// </see>
public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems)
{
return new InputBindingDescriptor(codon);
}
}
}

39
src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/RoutedUICommandDescriptor.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
using System;
namespace ICSharpCode.Core
{
/// <summary>
/// Stores information about routed UI command loaded from add-in tree
/// </summary>
public class RoutedUICommandDescriptor
{
private Codon codon;
/// <summary>
/// Text presented to user
/// </summary>
public string Text {
get {
return codon.Properties["text"];
}
}
/// <summary>
/// Routed command name
/// </summary>
public string Name {
get {
return codon.Properties["id"];
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="codon">Reference to codon used to create this descriptor</param>
public RoutedUICommandDescriptor(Codon codon)
{
this.codon = codon;
}
}
}

25
src/Main/Core/Project/Src/AddInTree/AddIn/DefaultDoozers/Command/RoutedUICommandDoozer.cs

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
using System;
namespace ICSharpCode.Core
{
/// <summary>
/// Creates descriptor containing information about routed UI command
/// </summary>
public class RoutedUICommandDoozer : IDoozer
{
/// <see cref="IDoozer.HandleConditions" />
public bool HandleConditions {
get {
return false;
}
}
/// <see cref="IDoozer.BuildItem(object, Codon, System.Collections.ArrayList)">
/// Builds RoutedUICommandDescriptor
/// </see>
public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems)
{
return new RoutedUICommandDescriptor(codon);
}
}
}

3
src/Main/Core/Project/Src/AddInTree/AddInTree.cs

@ -33,6 +33,9 @@ namespace ICSharpCode.Core @@ -33,6 +33,9 @@ namespace ICSharpCode.Core
doozers.Add("MenuItem", new MenuItemDoozer());
doozers.Add("ToolbarItem", new ToolbarItemDoozer());
doozers.Add("Include", new IncludeDoozer());
doozers.Add("InputBinding", new InputBindingDoozer());
doozers.Add("CommandBinding", new CommandBindingDoozer());
doozers.Add("RoutedUICommand", new RoutedUICommandDoozer());
conditionEvaluators.Add("Compare", new CompareConditionEvaluator());
conditionEvaluators.Add("Ownerstate", new OwnerStateConditionEvaluator());

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

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
using System;
using System.Reflection;
using System.Windows.Input;
using ICSharpCode.Core;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Description of CommandsService.
/// </summary>
public static class CommandsService
{
public static void RegisterRoutedUICommands(object caller, string path)
{
var descriptors = AddInTree.BuildItems<RoutedUICommandDescriptor>(path, caller, false);
foreach(var desc in descriptors) {
CommandsRegistry.RegisterRoutedUICommand(desc.Name, desc.Text);
}
}
public static void RegisterCommandBindings(object caller, string path)
{
var descriptors = AddInTree.BuildItems<CommandBindingDescriptor>(path, caller, false);
foreach(var desc in descriptors) {
var contextName = !string.IsNullOrEmpty(desc.Context) ? desc.Context : CommandsRegistry.DefaultContext;
CommandsRegistry.RegisterCommandBinding(contextName, desc.Command, desc.Class, desc.Codon.AddIn, desc.Lazy);
}
}
public static void RegisterInputBindings(object caller, string path)
{
var descriptors = AddInTree.BuildItems<InputBindingDescriptor>(path, caller, false);
foreach(var desc in descriptors) {
var contextName = !string.IsNullOrEmpty(desc.Context) ? desc.Context : CommandsRegistry.DefaultContext;
var gesture = (KeyGesture)new KeyGestureConverter().ConvertFromInvariantString(desc.Gesture);
CommandsRegistry.RegisterInputBinding(contextName, desc.Command, gesture);
}
}
}
}

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

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
using System;
using System.Windows;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Stores details about input binding
/// </summary>
public class InputBindingInfo
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="contextName">Context full name</param>
/// <param name="routedCommandName">Name of routed UI command which is triggered by this binding</param>
/// <param name="gesture">Gesture which triggers this binding</param>
public InputBindingInfo(string contextName, string routedCommandName, KeyGesture gesture) {
ContextName = contextName;
RoutedCommandName = routedCommandName;
Gesture = gesture;
}
/// <summary>
/// Context class full name
///
/// Described binding will be valid in this context
/// </summary>
public string ContextName {
get; 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>
/// Routed command name
///
/// Described binding triggers this routed command
/// </summary>
/// <seealso cref="RoutedCommand"></seealso>
public string RoutedCommandName {
get; set;
}
/// <summary>
/// Routed command instance
///
/// Described binding triggers this routed command
/// </summary>
/// <seealso cref="RoutedCommandName"></seealso>
public RoutedUICommand RoutedCommand {
get {
return CommandsRegistry.GetRoutedUICommand(RoutedCommandName);
}
}
/// <summary>
/// Gesture which triggers this binding
/// </summary>
public KeyGesture Gesture {
get; set;
}
}
}

41
src/Main/ICSharpCode.Core.Presentation/CommandsService/WpfCommandWrapper.cs

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
using System;
using System.Windows.Input;
using ICSharpCode.Core;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Wraps SharpDevelop's native command inside WPF command
/// </summary>
public class WpfCommandWrapper : System.Windows.Input.ICommand
{
ICommand command;
/// <summary>
/// Constructor
/// </summary>
/// <param name="command">SharpDevelop native command</param>
public WpfCommandWrapper(ICommand command)
{
this.command = command;
}
/// <see cref="System.Windows.Input.ICommand.CanExecuteChanged">
/// Not used because SharpDevelop's native command implementation
/// doesn't support it
/// </see>
public event EventHandler CanExecuteChanged;
/// <see cref="System.Windows.Input.ICommand.Execute(object)" />
public void Execute(object parameter)
{
command.Run();
}
/// <see cref="System.Windows.Input.ICommand.CanExecute(object)" />
public bool CanExecute(object parameter)
{
return true;
}
}
}

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

@ -51,6 +51,7 @@ @@ -51,6 +51,7 @@
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
@ -63,6 +64,13 @@ @@ -63,6 +64,13 @@
<Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="CommandsService\CommandBindingInfo.cs" />
<Compile Include="CommandsService\CommandsService.cs" />
<Compile Include="CommandsService\CommandsRegistry.cs" />
<Compile Include="CommandsService\InputBindingInfo.cs" />
<Compile Include="CommandsService\ManagedCommandBinding.cs" />
<Compile Include="CommandsService\ManagedInputBinding.cs" />
<Compile Include="CommandsService\WpfCommandWrapper.cs" />
<Compile Include="ConditionalSeparator.cs" />
<Compile Include="GetBitmapExtension.cs" />
<Compile Include="IStatusUpdate.cs" />
@ -89,6 +97,7 @@ @@ -89,6 +97,7 @@
<Private>False</Private>
</ProjectReference>
<Folder Include="Menu" />
<Folder Include="CommandsService" />
<Folder Include="themes" />
<Folder Include="ToolBar" />
<Page Include="themes\Aero.NormalColor.xaml" />

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

@ -118,6 +118,10 @@ namespace ICSharpCode.Core.Presentation @@ -118,6 +118,10 @@ namespace ICSharpCode.Core.Presentation
{
public MenuCommand(UIElement inputBindingOwner, Codon codon, object caller, bool createCommand) : base(codon, caller)
{
//if(!string.IsNullOrEmpty(codon.Properties["command"])) {
// this.Command = CommandsRegistry.GetRoutedUICommand(codon.Properties["command"]);
//}
this.Command = CommandWrapper.GetCommand(codon, caller, createCommand);
if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) {
KeyGesture kg = MenuService.ParseShortcut(codon.Properties["shortcut"]);

Loading…
Cancel
Save