Advanced GMF: Overview of Commands

Commands are a very important concept in the GEF MVC framework. To customize your GMF application it is very important to understand what they do and how they integrate into the overall framework. When you integrate in the command framework the framework provides hooks to add plenty of functionality, for example you can add undo, redo and transactional operations by implementing the corresponding interfaces. Thus you can focus on the core of the application logic and forget about boilerplate code. 

As a user of GMF you need to be aware of the following:

  • There are two Command frameworks, one for Eclipse and one for GEF
  • Different frameworks provide partial implementation of commands (abstract classes) for different applications, for example, EMF provides partial implementation of commands to deal with EMF models.
  • GMF provides partial implementations for commands dealing with EMF models and GEF commands. (so you don't need to make write the code to combine the two of them)

GEF Commands

GEF commands are the commands that extend the Command abstract class (org.eclipse.gef.commands). These commands are used by the GEF MVC framework. In particular, when you implement your custom EditPolicies you will be implementing this kind of command. Indeed, EditPolicies are expected to return such commands, and GEF tools are designed to execute them. By designed, I mean that the boilerplate code is already written for you.

EMF Commands

EMF provides a partial implementation of an Eclipse command that handles modification to EMF models: the AbstractEMFOperationEMF. By implementing one simple method (doExecute) you obtain a lot of functionality for free. In particular, all the IUndoableOperation interface is already implemented for you. The abstract class also handles the fact that a modification of the EMF model requires a transactional context. 

Handling Commands in GMF

GMF does not provide a command framework by itself but provides convenience implementations of the glue between the GEF command framework and the Eclipse command framework. GMF provides two classes to make these two frameworks work together: the AbstractTransactionalCommand abstract class and the ICommandProxy class.

AbstractTransactionalCommand is a subclass of AbstractEMFOperationEMF, and thus provides the same functionality as it. It also implements the ICommand interface. Classes implementing the ICommand interface can be converted to GEF Commands using the ICommandProxy class.

Finally, GMF also provides other implementations of ICommand. In particular the AbstractCommand class. The AbstractCommand class provides the same functionality as the AbstractEMFOperationEMF class, but for non EMF modifications.

Example

I present here a small example of a command in an EditPolicy:

public class TestEditPolicy extends AbstractEditPolicy {

 /**
  * The get command implementation.
  *
  * @returns a GEF command
  */
 @Override
 public Command getCommand(Request request) {
  // you should get the editing domain and the object you are working with
  // you can get the editing domain from the generated edit part
  TransactionalEditingDomain editingDomain = null;
  // here we wrap the AbstractTransactionalCommand into a command proxy
  // that implements GEF commands
  return new ICommandProxy(createCommand(null, editingDomain, "Command"));
 }

 private ICommand createCommand(final EObject object,
   TransactionalEditingDomain domain, String label) {
  // AbstractTransactionalCommand is an eclipse command to handle EMF models
  return new AbstractTransactionalCommand(domain, label, null) {

   // this is the only method to implement
   @Override
   protected CommandResult doExecuteWithResult(
     IProgressMonitor monitor, IAdaptable info)
     throws ExecutionException {
    // we can modify EObjects here
    object.eSetDeliver(true);
    return CommandResult.newOKCommandResult();
   }
  };
 }
}

If you enjoyed this post and would like to receive similar content directly in your inbox, please subscribe using the side bar form. Also, please do not hesitate to ask questions and give feedback in the comments!

References

 

tweet: