给GMF应用程序添加自定义Action

简介:

假设GMF为你生成的项目名称为com.example.diagram,现在要在右键菜单里增加一个自定义命令,并关联在名为Activity的模型元素上,即只有在Activity类型的元素上点右键,弹出菜单里才有这个自定义命令。此命令的功能是简单的把该Activity的Name属性改为“Modified Activity”。实现的步骤如下:

1、如果之前没有创建过,则创建一个名为com.example.diagram.custom的plugin项目(以下简称为“custom项目”),新建这个项目的目的是把自己的定制与GMF生成的代码分开;

2、在custom项目里实现org.eclipse.ui.popupMenus扩展点,这样会在右键菜单里多出一个"Change"菜单项,下面有"Name"命令;

<extension
         point="org.eclipse.ui.popupMenus">
  <objectContribution
        adaptable="false"
        id="com.example.custom.objectContribution.ActivityEditPart"
        objectClass="com.example.diagram.edit.parts.ActivityEditPart">
     <menu
           id="BMAChange"
           label="&amp;Change"
           path="additions">
        <separator name="group1"/>
     </menu>
     <action
           class="com.example.diagram.popup.ChangeActivityNameAction"
           enablesFor="1"
           id="com.example.diagram.popup.ChangeActivityNameAction"
           label="&amp;Name"
           menubarPath="BMAChange/group1"/>
  </objectContribution>
</extension>

3、实现上一步里定义的Action类ChangeActivityNameAction,这个类不仅要实现IObjectActionDelegate(popupMenus扩展点的要求),还要继承自AbstractActionDelegate这个类(GMF的要求)。我们要做的是实现doRun()方法,首先取得当前选中的editpart,然后创建一个SetRequest实例,它包含了改变属性操作的所有信息,包括目标对象、属性的名字和新属性值。因为GMF里editpart的getModel()方法不是业务模型里的元素了,而是View对象,要再调用View#getElement()才能得到业务模型里的元素,所以代码里我们利用ViewUtil#resolveSemanticElement()方法直接得到Activity对象。另外,GMF使用了EMFT的Transaction项目来操作模型,所以editpart.getEditingDomain()方法得到的会是一个TransactionalEditingDomain类型。

有了request,我们用它作为构造参数创建一个SetValueCommand(),这是一个GMF命令(实现org.eclipse.gmf.runtime.common.core.command.ICommand),用来改变属性值。最后要执行这个命令,我们知道command是要用CommandStack来执行的,这样才能undo/redo,但editpart.getDiagramEditDomain().getDiagramCommandStack()得到的CommandStack只能执行GEF的命令(org.eclipse.gef.commands.Command),所以要把我们的command用ICommandProxy()包装一下,这样就没问题了。

public class ChangeActivityNameAction extends AbstractActionDelegate 
                implements IObjectActionDelegate {

    protected void doRun(IProgressMonitor progressMonitor) {

        // Get the selected edit part
        IStructuredSelection structuredSelection = getStructuredSelection();
        Object selection = structuredSelection.getFirstElement();
        IGraphicalEditPart editpart = (IGraphicalEditPart) selection;

        // Create a command to modify its property
        SetRequest request = new SetRequest(
                editpart.getEditingDomain(),
                ViewUtil.resolveSemanticElement((View) editpart.getModel()),//The semantic model 
                BmaPackage.Literals.ACTIVITY__NAME,//Name feature of activity
                "Modified Activity");//New name value
        SetValueCommand command = new SetValueCommand(request);

        //Do the work
        editpart.getDiagramEditDomain().getDiagramCommandStack().execute(new ICommandProxy(command));

    }
}

Update: 可以用IGraphicalEditPart#resolveSemanticElement()直接取得editpart对应的EObject,IGraphicalEditPart#getNotationView()是得到View对象,和getModel()作用一样。

运行效果如下,选择修改名字命令后,Activity1的名字改为Modified Activity,并且可以undo/redo:

参考:

  • GMF提供的Logic例子中CreateLogicElementActionDelegate.java文件
  • GMF Tips,Change Names Of Newly Created Elements小节
  • GMF Tutorial Part 3

Update(2007/07/17):似乎GMF更推荐使用IOperationHistory来修改模型,例如在Action的doRun()方法里像下面这样写:

AbstractTransactionalCommand command = new AbstractTransactionalCommand(
        editingDomain,
        "Modifying the model", Collections.EMPTY_LIST) { 
    protected CommandResult doExecuteWithResult(
            IProgressMonitor monitor, IAdaptable info)
            throws ExecutionException {
        //在这里修改模型
        return CommandResult.newOKCommandResult();
    }
};
try {
    OperationHistoryFactory.getOperationHistory().execute(command,
            new SubProgressMonitor(progressMonitor, 1), null);
} catch (ExecutionException e) {
    MindmapDiagramEditorPlugin.getInstance().logError(
            "Unable to create model and diagram", e); //$NON-NLS-1$
}

因为在GMF新闻组里提到过:"in a GMF application, you should probably never execute commands in a CommandStack, because it will not be worth the effort of coordinating the IUndoContexts applied to these commands and your GMF AbstractTransactionalCommands to ensure that the Undo/Redo menus make sense.",原文链接

本文转自博客园八进制的博客,原文链接:给GMF应用程序添加自定义Action,如需转载请自行联系原博主。

相关文章
odoo context上下文用法总结
odoo context上下文用法总结
256 0
|
Java
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(二)
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(二)
144 0
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(二)
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(三)
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(三)
274 0
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(三)
|
设计模式 API 数据库
iOS 限制按钮的点击频率(Target-Action设计模式的运用)
iOS 限制按钮的点击频率(Target-Action设计模式的运用)
269 0
iOS 限制按钮的点击频率(Target-Action设计模式的运用)
|
XML Android开发 数据格式
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(一)
【鸿蒙 HarmonyOS】界面跳转 ( Page Ability 的 action 标识 | Page Ability 之间的界面跳转及传递数据 | 鸿蒙工程下创建 Module | 代码示例 )(一)
389 0
|
Web App开发 JavaScript 前端开发
给自定义控件(Web Control)添加事件的几种方法。前两种方法可以不实现IPostBackEventHandler
    写自定义控件已经好久了,也有几个用得时间比较长的,但是对于“事件”一直是比较模糊,没有很详细的理解。          最近升级分页控件,由于原来使用的是VB.net(在VB.net里面添加一个事件是比较容易的),现在想改用C#,而原来的方法又写得比较笨拙,想换一个更简洁一点的方法,所以不得不重新认识一下事件。
975 0
|
开发工具 开发者 Windows
UWP: 妙用自定义 Action 以简化并重用代码
原文:UWP: 妙用自定义 Action 以简化并重用代码     相信每一位 App 开发者,在开发过程中,都会有一些代码被反复用到,比如:复制文本,打电话,发短信,发邮件,给应用添加评论等等。在项目之间复制这些代码段,实在不是一个好办法,所以大家可能会把这些代码放到一个类似 Utility 类中,或者一个库(Class Library)中,再加以调用。
1299 0