We are going to learn how to leverage the capability of adding attributes to nodes. This feature is fully described in the Attributes section of the Structure chapter. In this cookbook we'll create a simple addition to the Calculator tutorial language that will allow the input and output fields of the calculator definitions to have descriptive comments attached to them. These descriptive comments will be propagated into the generated Java code in the form of "popup tooltips" attached to the Swing text fields corresponding to the input and output fields.
The Calculator language
We chose the Calculator tutorial language as a testbed for our experiments. You can find the calculator-tutorial project included in the set of sample projects that comes with the MPS distribution. I recommend you skimmed through the tutorial to familiarize yourself with the language before we continue.
Changes to the fields
Let's start building the machinery for adding descriptive comments to input and output fields. Our approach will be based on annotations that when added to nodes will have impact on their visual appearance as well as on the generated code. There are several vital components that will enable our desired functionality:
A marker interface that indicates, which nodes can hold the description comments
The annotation itself to indicate whether a node holds the description comment and what the description is
An action providing a keyboard shortcut to quickly add and remove the description comment to/from a node under caret
Updating the code generation process in order to generate the visual "tooltips" for the described components
We start with a new interface to mark all commentable nodes:
Now both InputField and OutputField concepts have to implement the new ICanHaveDescription interface.
The DescriptionAnnotation concept
We are still missing the core pice of our puzzle - the actual annotation that will be attributed to input and output fields to specify the description comment. Let's create it now:
Once you make the concept extend NodeAttribute, MPS will hint you to provide further information detailing the attribution. Invoking a quick-fix through Alt + Enter will add the necessary information for you to customize:
You need to specify additional qualities of the new annotation by setting values for role as well as attributed concepts. We set the role for the annotation as descriptionComment. This is the name to use in queries in order to find out, whether a node has been annotated with DescriptionAnnotation or not. We also indicate that the annotation can only be attributed to nodes implementing ICanHaveDescription, which in our case is InputField and OutputField.
The DescriptionAnnotation also has to store the actual text of the description - we'll use a string property descriptionText for this:
The editor of DescriptionAnnotation is the key element in defining the visual behavior of nodes with description comments attached to them. We prepend the annotated node with a "described" constant and append the actual description text wrapped in parentheses. The attributed node cell represents the editor of the actual node - the node that the attribute is attached to.
Further editor enhancements
To toggle the description comment of a node on and off, we will create new KeyMap.
To edit the code we will use concepts from BaseLanguage and smodel, which should be available by default. If not, import them through Control/Cmd + L. We will also need the actions language in order to create initialized nodes easily. This one will most likely need to be imported explicitly (Control + L).
Now we can complete the action:
Whenever Control + Alt + Shift + D is pressed on a node implementing ICanHaveDescription, the action will add or remove the DescriptionAnnotation to/from the node.
The KeyMap now needs to be added to all fields that should react to Control + Alt + Shift + D. This is to InputField and OutputField in our case. The editor cells that should react to the Control + Alt + Shift + D key combination must have the key map specified in the keycap property.
How are we doing so far?
After compilation you are able to use Control + Alt + Shift + D both on input fields and output fields to toggle the description comment:
Updating the generator
The DescriptionAnnotation is currently lost during the generation process. Instead, we would like to generate the Swing "tooltips" for the text fields that represent the commented input and output fields.
When generating code we currently take all input or output fields in the calculator and generate JTextFields for them. In the constructor we also generate initialization code for each generated JTextField - this is the place, where we can attach a Swing "tooltip" the JTextFields that represent an input or output fields with description comments.
The $IF$ node macro will ensure that a "tooltip" is only generated for nodes with the DescriptionComment annotation attached.
The property macro of the text of the "tooltip" will set the descriptionText of the DescriptionAnnotation attached to the current node:
After rebuilding the language and the sandbox solution, the generated Calculator form will have "tooltips" attached to the fields that have been marked with the DescriptionAnnotation:
We can finish our tour here. Both input fields and output fields can be described with DescriptionAnnotation and the generated code contains a "tooltip" for each such description.