给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,如需转载请自行联系原博主。

相关文章
|
数据可视化 Python
数据可视化之matplotlib绘制饼状图
数据可视化之matplotlib绘制饼状图 常常为Python的数据可视化而痴迷,将数据进行可视化只需要掌握相关库的方法使用即可。流水线式的库式调用实现正是显示python强大的库的功能。我们可以绘制各种各样的数据图样式,对于数据的反应更加直观而准确。
482 0
数据可视化之matplotlib绘制饼状图
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
对大模型和AI的认识与思考
2023年,笔者也参与了各种学习和实践,从大语言模型、多模态算法,文生图(Stable Diffusion)技术,到prompt工程实践和搭建文生图(Stable Diffusion)webui实操环境。在此对谈谈对大模型和AI的认识与思考,是为总结。5月更文挑战第3天
153 1
|
存储 传感器 负载均衡
移动无线通信技术经历了哪些变迁? | 《5G移动无线通信技术》之一
本书全面地介绍了全球范围内对5G应用和需求、网络架构和关键技术的研究成果。对于在通信行业的专家、学者、工程师和在校学生,以及关心移动无线通信技术 5G技术和应用的读者都有较高的参考价值。
移动无线通信技术经历了哪些变迁? | 《5G移动无线通信技术》之一
|
9月前
|
传感器 人工智能 算法
掌握C++中的状态-事件回调矩阵:打造强大的有限状态机
掌握C++中的状态-事件回调矩阵:打造强大的有限状态机
211 0
|
算法
【计算机网络】数据链路层学习笔记(二)差错检测和纠错及汉明码详解
本文的重点就是掌握典型的码的思想,以触类旁通。
557 0
|
Kubernetes 负载均衡 Cloud Native
云原生|kubernetes|解决kube-proxy报错:Not using `--random-fully` in the MASQUERADE rule for iptables
云原生|kubernetes|解决kube-proxy报错:Not using `--random-fully` in the MASQUERADE rule for iptables
646 0
|
C#
【C#/WPF】Bitmap、BitmapImage、ImageSource 、byte[]转换问题
原文:【C#/WPF】Bitmap、BitmapImage、ImageSource 、byte[]转换问题 C#/WPF项目中,用到图像相关的功能时,涉及到多种图像数据类型的相互转换问题,这里做了个整理。
4556 0
|
消息中间件 Shell API
RT-Thread记录(十三、I/O 设备模型之PIN设备)
讲完UART设备之后,我们已经熟悉RT-Thread I/O 设备模型了,回头看看基本的 PIN 设备。
444 0
RT-Thread记录(十三、I/O 设备模型之PIN设备)
|
数据可视化 Python
QWidget:Must construct a QApplication before a QWidget。
异常描述:       用PyQt开发的界面程序,再新增加了几个module后,     在eric6开发环境下启动后什么都没出现,什么错误提示也都没有,     在控制台下:python   XXXX.py 后显示 QWidget:Must construct a QApplication before a QWidget。
2734 0

热门文章

最新文章

相关实验场景

更多