欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

重定向Retarget Action 小结 博客分类: eclipseGEF 菜单重定向retarget action

程序员文章站 2024-03-20 00:03:04
...

根据资料系统整理、明确一下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)。