-
Notifications
You must be signed in to change notification settings - Fork 83
Commands
Commands are units of work triggered by a user. They are usually triggered in one of the following ways:
- Button clicked
- Menu item clicked
- Hotkey pressed
- Command selected from the command box
In the BSP editor, commands will quite often commit a change or display a dialog. Examples of commands include menu items such as "Tools > Carve", "File > Save", and "Help > Check for updates".
Required reading: Exporting and importing classes
If you want to add a new command that edits a map, inherit a class from Sledge.BspEditor.Commands.BaseCommand
. The class has one abstract method Invoke(MapDocument, CommandParameters)
that must be implemented, as well as Name
and Details
properties.
All commands should have a uniquely identifiable id, specified by using the CommandID
attribute.
Here's a simple example of a command:
[Export(typeof(ICommand))] // Export the command so it's available to use
[CommandID("Examples:Example1")] // Must be a unique string to identify this command
public class ExampleCommand : BaseCommand
{
public override string Name { get; set; } = "Do the thing"; // The name of the command
public override string Details { get; set; } = "Does a thing"; // A short description of the command
protected override async Task Invoke(MapDocument document, CommandParameters parameters)
{
// Code that runs when the command is invoked
System.Windows.Forms.MessageBox.Show("This is an example.");
}
}
Required reading: Context and context changes
By default, the base command will be runnable if the active document is a MapDocument
, but you can change this by overriding the IsInContext(IContext, MapDocument)
method.
In this example, the command will only be allowed if the current selection is non-empty:
// ...
public class ExampleCommand : BaseCommand
{
protected override bool IsInContext(IContext context, MapDocument document)
{
return !document.Selection.IsEmpty;
}
// ...
}
Required reading: Supporting translations
Simply tag the class with [AutoTranslate]
to automatically translate the Name
and Details
properties in your command. The properties must have a public setter. The translation text will be taken from the corresponding keys in your assembly's translations file(s).
[AutoTranslate]
// ...
public class ExampleCommand : BaseCommand
{
// The set methods must be public to use auto translations
public override string Name { get; set; }
public override string Details { get; set; }
// ...
}
Required reading: Menu sections and groups • Order hints
Adding commands to the menu is as simple as appending a MenuItem
attribute to your class. You can specify a menu icon using the MenuImage
attribute as well.
[MenuItem("Examples", "", "Test", "M")] // Command will appear in the "Examples" menu section, the "Test" menu group, using "M" as the ordering hint
[MenuImage(typeof(Resources), nameof(Resources.Menu_Example))] // (Optional) This should identify an image resource in your assembly
// ...
public class ExampleCommand : BaseCommand
{
// ...
}
For slightly more control over your command, or if you're using a custom document type, you will need to implement the ICommand
interface directly. All the previous rules remain the same, but the methods change slightly. To extract useful parameters for your command you will need to use the context, be sure to read the context tutorials.
Here's a very basic example to demonstrate an ICommand
implementation:
[Export(typeof(ICommand))]
[CommandID("Examples:Example2")]
public class ExampleCommand : ICommand
{
public string Name { get; set; } = "Example";
public string Details { get; set; } = "Example";
public bool IsInContext(IContext context)
{
return true;
}
public async Task Invoke(IContext context, CommandParameters parameters)
{
MessageBox.Show("Hello.");
}
}