您的位置:首页 > 其它

RssOwl2源码阅读 -- ActionSet

2008-11-23 16:59 169 查看
ActionSet是Eclipse RCP里面一非常重要的概念,因为菜单、工具栏、上下文菜单、状态栏很多操作都是共享的,所以Action就是用来处理重复出现的东西。至于Eclipse里面定义ActionSet有非常多的技巧,可能无法一一列举,而且使用方法也多种多样。下面介绍的是RssOwl2项目的ui源代码部分的一小块。
1. 菜单的插入点 -- GroupMarker和Separator的使用
ApplicationActionBarAdvisor类是定义全局所有Action插入点和入口,查看fillMenuBar(IMenuManager)方法,为了简化,以其中的辅助方法createFileMenu(IMenuManager)为例,讲述一下实现菜单“文件”的内容,先看一下菜单的结构



像Close,Import...之类的非常简单,看一下它是如何实现New这个子菜单的。首先看一下它的源代码如何定义插入点




/**//* Menu: File */




private void createFileMenu(IMenuManager menuBar)

{


MenuManager fileMenu = new MenuManager("&File", IWorkbenchActionConstants.M_FILE);


menuBar.add(fileMenu);




fileMenu.add(new GroupMarker(IWorkbenchActionConstants.FILE_START));


fileMenu.add(new GroupMarker(IWorkbenchActionConstants.NEW_EXT));


fileMenu.add(new Separator());




fileMenu.add(getAction(ActionFactory.CLOSE.getId()));


fileMenu.add(getAction(ActionFactory.CLOSE_ALL.getId()));


fileMenu.add(new GroupMarker(IWorkbenchActionConstants.CLOSE_EXT));


fileMenu.add(new Separator());


fileMenu.add(getAction(ActionFactory.SAVE_AS.getId()));


fileMenu.add(new GroupMarker(IWorkbenchActionConstants.SAVE_EXT));


fileMenu.add(new Separator());


fileMenu.add(getAction(ActionFactory.PRINT.getId()));




fileMenu.add(new Separator());


fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));




fileMenu.add(fReopenEditors); // TODO Consider moving into a "Go" Menu!




fileMenu.add(new Separator());


fileMenu.add(new GroupMarker(IWorkbenchActionConstants.FILE_END));


fileMenu.add(new Separator());




fileMenu.add(getAction(ActionFactory.QUIT.getId()));


} 其中有一行fileMenu.add(new GroupMarker(IWorkbenchActionConstants.NEW_EXT)); 这里是定义一个GroupMarker作为组标记,把子菜单New容纳进来。这个NEW_EXT的值是:new.ext
现在跳回到plugin.xml去看一下它的ActionSet定义,结构如下:


,点击New(menu),它的path值为:file/new.ext,这个路径就是在createFileMenu方法定义的路径,第一个是“File”本身的ID。也就是把子菜单New(menu)插入到指定的那个GroupMarker,ID为new.ext。然后定义了三个ID分别为bookmark,newsbin,searchmark,的groupmarker和一个folder的separator,这个三ID分别就对应上面actionSet定义的三个action,以其中的Bookmark(action)为例,它的menubarPath为:file/new_sub/bookmark,代表插入到"File"主菜单中定义的new_sub子菜单中,new_sub是New(menu)的ID。因为folder是定义为separator,所以它会有一条分隔线。这只是RssOwl的定义方法,其实以前自己做开发的时候是没有这样定义的,而且把子菜单New也写在方法fillMenuBar中的,菜单把ID都写在里面,ActionSet的配置就没有子菜单出现了,但是这样定义看起来就比较乱。采用这种写法感觉比较简洁。
2. Action的实现
仍以bookmark为例,它的实现类是NewBookMarkAction,实现了IWorkbenchWindowActionDelegate, IObjectActionDelegate二个接口,第一个是ActionSet指定实现接口,第二个是对象操作菜单要求实现的接口(但事实发现没有再定义它的配置,可能是internal版本的原因),也就是说这个Action是多功能,它将会出现在主菜单,工具栏,和局部的右键菜单上。主菜单和工具栏的位置都在ActionSet配置定义了,看看它的右键菜单实现是在哪里的,这个右键是在视图Bookmarks定义的,那么跳转到org.rssowl.ui.internal.views.explorer.BookMarkExplorer类去看看。里面有一个hookContextualMenu()方法,就是定义它的右键菜单的,看一下代码实现:




private void hookContextualMenu()

{


MenuManager manager = new MenuManager();






/**//* New Menu */


MenuManager newMenu = new MenuManager("New");


manager.add(newMenu);






/**//* New BookMark */




newMenu.add(new Action("Bookmark

")

{


@Override




public void run()

{


IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();


IFolder parent = getParent(selection);


IMark position = (IMark) ((selection.getFirstElement() instanceof IMark) ? selection.getFirstElement() : null);


new NewBookMarkAction(fViewSite.getShell(), parent, position).run(null);


}




@Override




public ImageDescriptor getImageDescriptor()

{


return OwlUI.BOOKMARK;


}


});




//其它定义



} 原来实现也很简单,只是往MenuManager里面添加一个Action而已,而且run方法就是直接调用定义好的NewBookMarkAction的run方法,但是把选中对象做为参数传进去,因为这个new是涉及当前上下文选择对象的。
3. 下拉类型的工具按钮定义
非常常见的Dropdown类型的工具栏按钮可以把功能类型的按钮归为一类,做成一个下拉菜单形式,有默认的按下功能,也有可以选择其它类似功能的下三角形式,样子如下:



这个dropdown的Action是定义在ActionSet配置里的。style是pulldown类型的,所以实现类NewTypeDropdownAction实现了IWorkbenchWindowPulldownDelegate接口,它的run方法就是定义默认点击不做选择时的事情,这个下拉菜单是实现getMenu(Control parent)方法而来,它定义了如何生成这个菜单,这就用到了最原始的SWT中的MenuItem了,并且为它们添加SelectionListener,方法实现,不用说都知道了,又是New一个先前定义好的NewBookMarkAction类,然后又是调用它的run方法。所以总结一下,Action的重用不一定是这个类的重用,关键是它的run方法的重用,在不同的场景下它的外在表现形式可能会多种多样,但是它的run内容是一致的。像添加这种添加的run大部分时候都是弹出一个对话框,而对话框大都又是Winzard类型的,因为Winzard可以共享放到dialog里面。所以这种复用的思想在Eclipse里面随处可见。
归结一下,其实这些技巧都是次要的,因为做GUI一个比较痛苦的事情就是经常要写很多重复类似的代码,抽取的不好,可能就变得不伦不类了。怎么利用它的这种思想,把复用的代码都抽取在一起,而阅读起来又比较轻松才是关键。
知道的就这些,先介绍到这里,下次再谈谈其它新的发现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: