Introduction
When you use the DSL SDK to create a tool with which to draw out your domain, you may have functionality that only applies to one class (or diagram element) in that model. This tip allows you to create a context sensitive menu for that case.
Background
Creating a domain specific language requires the Visual Studio Modelling SDK to be installed.
When you create a new domain specific language modelling project, Visual Studio creates a solution with two projects in it: a Dsl
project that controls the diagramming component and a DslPackage
project that controls how the IDE (or indeed any other modelling host) interacts with the diagram.
The changes required to create a context sensitive menu go in the DslPackage
project.
1. Create a New Menu for the IDE to Use
In the DslPackage
project is a file called "Commands.vsct". You need to edit this to add any interactions you want the IDE to host. In an echo back to Visual C, you do this by creating a menu identifier and associating it to the command.
<Symbols>
<GuidSymbol name="guidCustomDiagramMenuCmdSet"
value="{986DE2DB-3F48-429B-8474-1248E06D8C27}" >
<IDSymbol name="grpidDiagramMenuGroup" value="0x01001"/>
<IDSymbol name="cmdidExpandCollapseAggregateContextMenuCommand" value="0x00003"/>
</GuidSymbol>
</Symbols>
This registers two identifiers - one for the top level command group the menus are going to go into and one for the command itself. The value=
part must be unique for each item.
The actual menus are created in the Buttons
tag:
<Buttons>
<Button guid="guidCustomDiagramMenuCmdSet"
id="cmdidExpandCollapseAggregateContextMenuCommand"
priority="0x0100" type="Button">
<Parent guid="guidCustomDiagramMenuCmdSet" id="grpidDiagramMenuGroup"/>
<CommandFlag>DefaultDisabled</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText>Expand/Collapse Aggregate</ButtonText>
</Strings>
</Button>
</Buttons>
Note that the ids of these buttons have to match the names of the symbols you created earlier, and the ButtonText
indicates the caption that will be shown on the menu.
2. Creating the Code for the Menus
When you rebuild this project, the partial class "CommandSet
" will be created for these commands. You will need to add your own code to a partial class of the same name to implement the command menu itself. (Do not put this code in the automatically generated file or it will be lost when you rebuild the project).
The first thing you need to do in your class is restate the constants you put in the Symbols
tag in step 1:
internal partial class CommandSet
{
private Guid guidCustomDiagramMenuCmdSet = new Guid("986DE2DB-3F48-429B-8474-1248E06D8C27");
private int cmdidExpandCollapseAggregateContextMenuCommand = 0x00003;
Then you need to override the GetMenuCommands
function so as to add your menus into the tool's menus:
protected override IList<MenuCommand> GetMenuCommands()
{
global::System.Collections.Generic.IList<global::System.ComponentModel.Design.MenuCommand>
commands = base.GetMenuCommands();
global::System.ComponentModel.Design.MenuCommand menuCommand = null;
menuCommand = new DynamicStatusMenuCommand(new EventHandler(OnStatusExpandCollapseAggregate),
new EventHandler(OnMenuExpandCollapseAggregate),
new CommandID(guidCustomDiagramMenuCmdSet,
cmdidExpandCollapseAggregateContextMenuCommand));
commands.Add(menuCommand);
return commands;
}
There are two methods you need to pass to this constructor for the new menu - the "OnStatus...
" method which is called whenever the IDE is deciding to if (or how) show the menu and the "OnMenu...
" method which is called when the menu is clicked.
In the case of the OnStatus
method, we want the menu to be shown and enabled only if there is one and only one "Aggregate
" selected (this being one of our diagram shape types defined in the Dsl
project).
internal virtual void OnStatusExpandCollapseAggregate(object sender, System.EventArgs e)
{
global::System.ComponentModel.Design.MenuCommand cmd =
sender as global::System.ComponentModel.Design.MenuCommand;
cmd.Visible = true;
cmd.Enabled = false;
if (this.CurrentSelection.OfType<AggregateGeometryShape>().Count() == 1)
{
cmd.Enabled = true;
}
}
History
- 2015-07-15: Created first draft