重定向Retarget Action 小结

2 篇文章 0 订阅

根据资料系统整理、明确一下Retarget Action这个概念(以在GEF中的应用为例)。

概念

它是一种具有一定语义但没有实际功能的action。它唯一的作用是在主菜单或是主工具条上占据一个位置,编辑器将具有实际功能的action映射到这个Retarget Action上,当编辑器被激活时,这个Retarget action将具有那个action的功能。

举例,eclipse提供了IWorkbenchActionConstants.COPY这个retarget Action它的文字、图标登时预先定义好的,而ABCAction是一个具体的动作类,通过在某个editor getEditorSite().getActionBars().setGlobalActionHandler(IWorkbenchActionConstants.COPY, ABCAction)就实现了映射。

一般地,eclipse自带的actionredo/undo等)绑定到eclipse自带的常量id上。自己定义的action绑定到自己的常量id上。当然,也可以交叉。

Eclipse引入RetargetAction的目的是为了尽量减少菜单/工具条的重建消耗,利用用户使用上的一致性。

重定向操作分类

重定向的操作分为eclipse已定义的操作和未定义的操作,已定义的操作如redo/undo等;未定义的操作就是自己需要定义的操作。

重定向绑定id方式

1通过contributorClass的实现类,在该类内部的buildActions()方法中新建,并用addRetargetAction()方法绑定。

2不用buildActions内创建新类,隐含在GEFeditor内部的createActions()方法中调用super.createActions()也可以创建(对于非eclipse定义的操作,我们在createActions()中自己添加)。这时可以在contributorClass类的declareGlobalActionKey()方法通过调用addGlobalActionKey()来绑定。

3不利用contributorClass类,而在GEF的编辑器初始化时,在createActions()方法中创建action添加到actionRegistry中,并利用类似下面的代码绑定操作:

比如,在initializeGraphicalViewer()方法中通过getEditorSite().getActionBars()得到actionBars,并通过getActionRegistry()方法得到actionRegistry

//………

//准备从ActionRegistry中找actionId对应的处理动作

        ActionRegistry registry = getActionRegistry();

        //actionBar上按钮的重定向

        IActionBars bars = this.getEditorSite().getActionBars();

        IToolBarManager toolBarManager = bars.getToolBarManager();

        //actionid

        String id = ActionFactory.UNDO.getId();

        bars.setGlobalActionHandler(id, registry.getAction(id));

        //动作绑定到工具栏上

        toolBarManager.add(registry.getAction(id));

GEF编辑器菜单/工具条

与视图不同编辑器没有自己的菜单和工具条,它的菜单只能添加到主菜单内,因此在扩展编辑器的时候,元素有一个contributorClass属性。通过这个属性定义的类的buildActions()方法将菜单重定向到主菜单上。

    protectedvoid buildActions() {

        addRetargetAction(new UndoRetargetAction());

        addRetargetAction(new RedoRetargetAction());

        addRetargetAction(new DeleteRetargetAction());

 

    }

    publicvoid contributeToToolBar(IToolBarManager toolBarManager) {

        toolBarManager.add(getAction(ActionFactory.UNDO.getId()));

        toolBarManager.add(getAction(ActionFactory.REDO.getId()));

}

publicvoid contributeToMenu(IMenuManager menuManager)

    {

        super.contributeToMenu(menuManager);

        IMenuManager mgr = new MenuManager("&Node","Node");

        //插入到主菜单上编辑的后面

        menuManager.insertAfter(IWorkbenchActionConstants.M_EDIT, mgr);

        mgr.add(getAction(IConstants.ACTION_A));

        mgr.add(getAction(IConstants.ACTION_B));

        mgr.add(getAction(IConstants.ACTION_C));

 }

    /*

     * 对于已经有的Retarget Action,我们应该在这个方法中调用addGlobalActionKey()方法来声明

     * 当编辑器被激活时,在globalActionKeys中的id指向的action将被映射到regargetAction上。

     * 不再需要setGlobalActionHandler("id",handler).因此上面buildActions()中可以删除,变为下面形式

     */

    protectedvoid declareGlobalActionKeys() {

        addGlobalActionKey(ActionFactory.UNDO.getId());

        addGlobalActionKey(ActionFactory.REDO.getId());

        addGlobalActionKey(ActionFactory.DELETE.getId());

    }

创建自己的action

GEF内没有定义的相应的action,这些action是这个编辑器所独有的。假定,我们选择的3figure,要给这3figure统一设定优先级属性。即当选中这几个figure时,我们插入到主菜单中的设定优先级的action可用。

我们建立的action应该是gefSelectionAction的子类,因为我们需要对选中的figure操作。还需要将action添加到selectionActions中。

privatevoid createMyActions() {

        // subSelectionAction1应该是gefSelectionAction的子类

        IAction subSelectionAction1 = null;

        subSelectionAction1.setId("");

        getActionRegistry().registerAction(subSelectionAction1);

        getSelectionActions().add(subSelectionAction1.getId());

       

        IAction action2 = null;

        action2.setId("");

        getActionRegistry().registerAction(action2);

        getSelectionActions().add(action2.getId());

    }

这个selectionAction需要自己实现calculateEnabled()方法。另外,因为在GEF编辑器中的动作都是支持redo/undo的。因此我们需要在这个action.run()的时候创建命令并推入命令栈,action的运行是靠命令,而不是直接运行。如果选中的figure3个,可能需要创建3个命令,这时为执行redo/undo也能一次性操作,而不是一个一个的来,可能需要一个CompoundCommand.3个命令组合成一个命令。注意的是:在创建命令之前判断选中的figure对应的editpartgetSelectedObjects())是否是可以执行action的对象。

GEF编辑器上下文菜单

GEF Editor中的configureGraphicalViewer()方法中,添加代码

//右键菜单

        MyContextMenuProvider provider = new MyContextMenuProvider(getGraphicalViewer(), getActionRegistry());

        this.getGraphicalViewer().setContextMenu(provider);

即可。

其中MyContextMenuProvidergefcontexMenuProvider的子类(而contextMenuProviderjface.actionMenuManager的子类),我们需要实现buildContextMenu()方法,在该方法中一般第一句调用GEFActionConstantS.addStandardActionGroups(menu);以对上下文菜单项添加默认分组。然后将action添加到分组中(action复用actionRegistry中的action)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值