A contextual command will appear only under certain conditions defined by the parameters set for it at the creation of the module command.

This is a first level of command filtering, based on static data: kind of object and behavior for read-only objects. Although this checking is performed at runtime for each right-click event on a UML element, it is called static filtering because it is defined statically at the creation.

A second level of command filtering, which is left completely to the module developer code, is also proposed by module commands. This second level of command filtering is called dynamic filtering as it is evaluated by running the module developer code. In practice, a dedicated accept() method that will be called by Modelio each time the Module command can be proposed has to be provided. The accept() method boolean returned value indicates whether or not the command has to be made available to the end-user.

This gives the module developer a means of dynamically checking conditions that could otherwise not be statically defined.

Commands that have passed both the active and dynamic filtering will be displayed, but can be inactive, grayed out.

Determining the graying of a command is also a two step process. First, static graying rules will be applied, and second, if the isActiveFor() method is defined, dynamic graying occurs.

Static graying rules are typically command declared to modify the model when the selected element is read-only.

Note that the dynamic filtering conditions (the developer’s coded filter) will not be evaluated (no call) if the command does not satisfy the static filtering criteria. The same rule applies for graying.

In short :

  • accept method is called to dynamically check if the command is visible;

  • isActiveFor method is called to dynamically check if the command is actionable or grayed out;

  • The order of check is : static filtering, dynamic filtering (accept), static graying and dynamic graying.

Writing command method

The next thing we have to do now is to complete the methods actionPerformed() and accept() with their implementation code.

The accept() method is called to validate the availability of the command in the current selection context. The current selection context is simply passed as the list of the currently selected elements.

For our example, let’s consider that the command accepts only one selected element.

    class CreateTestCase extends DefaultModuleContextualCommand {
    ...
    public boolean accept( List<MObject> selectedElements, IModule module)
    {
        // Check that there is only one selected element
        return selectedElements.size() == 1;
    }
    ...
    }

The actionPerformed() command is called when the command is activated by the end-user. Its role is to perform the proper action. Thus, the code of this method is the action itself.

class CreateTestCase extends DefaultModuleContextualCommand {
    ...
    public void actionPerformed( List<MObject> selectedElements, IModule module)
    {
        // Process the command, in our case display the Create Test wizard dialog
        CreateTestCaseWizardDialog dlg = new CreateTestCaseWizardDialog(selectedElements.get(0), module);
        dlg.open();
    }
    ...
}

That’s it!

Of course, you can see that the proposed actionPerformed() method only delegates the expected behavior to a CreateTestCaseWizardDialog object. This is explained by the fact that we need to pop up quite a rich and complicated GUI to fetch parameter values from the user before performing the intended action. Coding the complete GUI in the actionPerformed() method is not a recommended practice, which is why we choose to use an additional class to implement the "Create a Test Case" wizard feature.

Coding this graphical wizard is outside the scope of this document, as it would produce a lot of code that is more directly related to GUI development than to Module programming. However, note that this code can be standard SWT code without any particular problem.

What is important next for our example is that at some point, the Module will have to perform the real Test Case creation, and modify and update the test model.