八进制

少年壮志无烟抽

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  244 随笔 :: 0 文章 :: 3241 评论 :: 14 引用

假设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.",原文链接

posted on 2006-09-06 14:57 八进制 阅读(2974) 评论(19)  编辑 收藏 网摘 所属分类: EclipseGMF

评论

#1楼 2006-10-07 14:08 幽幽西山      
八进制大侠,能不能多写些关于GMF的文章!
  回复  引用  查看    

#2楼 2006-11-01 14:00 tz[未注册用户]
请问八进制:如果我想在view中,比如package explorer。也加上如上文所提到的自定义action,应该怎样做了。先谢谢了
  回复  引用    

#3楼 2006-11-01 14:12 tz[未注册用户]
在考虑是否可以让两者共用一个action。不知道八进制有没有什么好的建议
  回复  引用    

#4楼[楼主] 2006-11-01 15:17 八进制      
让这个action实现IViewActionDelegate接口,然后在plugin.xml里通过org.eclipse.ui.viewActions扩展点加到view上应该就可以了吧。
  回复  引用  查看    

#5楼 2006-11-01 18:35 tz[未注册用户]
知道怎么做了,谢谢八进制
  回复  引用    

#6楼 2006-11-06 09:49 tz[未注册用户]
你好八进制,我给view加上了修改名字的action之后。想要view的contexmenu像editor中一样也有undo,redo的功能。不知道可否这样,如果可以的话应该怎样做了。
  回复  引用    

#7楼[楼主] 2006-11-07 13:39 八进制      
把这两个action通过plugin.xml文件contribute到上下文菜单吧,也许需要实现IObjectActionDelegate接口。
  回复  引用  查看    

#8楼 2006-11-07 18:12 tz[未注册用户]
我试试看,谢谢
  回复  引用    

#9楼 2007-08-26 08:49 z[未注册用户]
能不能把这个代码包发给我,非常感谢
  回复  引用    

#10楼 2007-08-26 08:50 z[未注册用户]
55104747@163.com
  回复  引用    

#11楼 2007-08-26 09:26 z[未注册用户]
editingDomain,这个参数怎么得到?
  回复  引用    

#12楼 2007-08-26 09:29 z[未注册用户]
BmaPackage.Literals.ACTIVITY__NAME,或是这个参数如何得到?
  回复  引用    

#13楼[楼主] 2007-08-26 21:43 八进制      
TransactionUtil.getEditingDomain(eobject)可得到editingDomain;XXXPackage是EMF生成的类。
  回复  引用  查看    

#14楼 2007-08-27 10:10 z[未注册用户]
找到了,非常感谢。
  回复  引用    

#15楼 2008-06-13 13:05 eaye[未注册用户]
八进制,你好!我刚刚接触GMF,在趟过各种问题后我终于能用自己的例子画图了。但还不能满足,想通过自己的图来生成代码,但我在网上找了好久,总是搞不清楚,难道还要在我用GMF项目生成的diagram项目里自己手工添加扩展点来新增Action吗?可不可以完全在我的GMF项目里定义这些扩展点的功能,然后通过.gmfgen模型一次全生成,这多好呀,例如修改.gmfgen来添加一个菜单和Action什么的?请指点:)
  回复  引用    

#16楼[楼主] 2008-06-13 20:55 八进制      
gmf提供了不少扩展点,其中有用于添加菜单/工具条的(org.eclipse.gmf.runtime.common.ui.services.action.contributionItemProviders),但也是要在生成代码后自己添加。
  回复  引用  查看    

#17楼 2008-06-14 03:02 eaye[未注册用户]
太感谢了,但我始终觉得手工修改生成的项目代码多少有些违背了GMF项目的思想,呵呵。但没办法了,哈哈
  回复  引用    

八进制大哥,关注你的博客已经有快半年的时间了,因为我也是一名GEF技术的爱好者,发现从你的博客中能学到很多GEF技术的高级应用,很受用,也十分感激;
最近使用GEF开发程序的过程中,遭遇了一个问题,简单来说就是如何通过扩展popmenu扩展点来实现GEF相关的Action:
我现在做了一个GEF程序,有一个aciont 姑且叫它action_one吧,为了能够调用GEF中的command,我让它extends SelectionAction了;现在我想通过popmenu扩展点的方法,调用这个action,由于popmenu要求所有action要实现IObjectActionDelegate接口,所以我把action_one改造成了诸如action_one extends SelectionAction implements IObjectActionDelegate 的形式,可是发现其中的run方法并不能正常调用?难道popmenu中不能实现GEF的command吗?还是说仅能通过你在本文所提到的这一种方法呢?

  回复  引用    

#19楼 2009-02-23 20:02 xiaobai[未注册用户]
请问GMF绘制的图片能够添加移动 旋转 等简单的动作么?
  回复  引用    

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 496394


历史上的今天:
2005-09-06 导出Plugin的一点心得
2004-09-06 二年级喽!

相关文章:

相关链接: