Posted on 2008-07-31 15:13
寒武纪 阅读(2084)
评论(5) 编辑 收藏 所属分类:
Eclipse
许久没有弄RCP了,刚好近来闲暇一点,找来个RSSOwl的源代码看看,有点收获。RssOwl非常出名,只是可能很多人不知道它是用Java做的。以前看过RssOwl第一版的源码,没有详细研究,down下来之后放上公司的共享CVS服务器,倒是几个同事饶有兴趣地研究起来。第一个版本写得较早,可能Eclipse的RCP框架都还没有出来,所以全部采用的SWT/JFace实现,主窗体就用的JFace里面的ApplicationWindow包装起来的。粗看了一下,感觉代码划分和设计得不错,把UI编码的大部分重复功能都抽取出来,那时候做项目,就经常从里面挖些代码出来用。现在上它的主页http://www.rssowl.org/,新设计的RssOwl 2 是基于RCP重构的,已经到了M8版本,主页的download没有直接的源代码包下载,只提供了SVN库,可以从里面check出来,地址是:https://rssowl.svn.sourceforge.net/svnroot/rssowl。拿出来后,总共是12个插件项目,相互关联。示意图如下:
从org.rssowl.build项目中的rssowl.product启动该RCP程序。可以预览到全部界面。看一张预览图。

非常漂亮,具体功能可以自己感受一下。
主要的代码都集中中org.rssowl.ui和org.rssowl.core二个插件,看标题就明白是什么意思,它本身的存储采用的是db4o,看来还是比较前卫哦。上面的主菜单中有一个view,也就是我们常在IE外壳等上面看到的“查看”菜单,里面有,“工具栏,侧边栏,状态栏”等等这些,可以隐藏或是显示,菜单项是check风格的。由于现在RssOwl 2仍处于Milestone阶段,所以很多代码仍是internal包里面的,以后肯定会慢慢变成公开的,做法和Eclpise如出一辙。
看一下org.rssowl.ui里面的代码,下面这几个非常熟悉的类。

菜单的设置就在ApplicationActionBarAdvisor.java类里面。为了简单起见,我把它的代码抽取出来,重新修改了一部分。如下:
@Override

protected void fillMenuBar(IMenuManager menuBar)
{
//
创建其它菜单
createViewMenu(menuBar);
MenuManager toolMenu = new MenuManager("工具(&T)",
IWorkbenchActionConstants.M_WINDOW);
menuBar.add(toolMenu);
toolMenu.add(prefAction);
MenuManager helpMenu = new MenuManager("帮助(&H)",
IWorkbenchActionConstants.M_HELP);
menuBar.add(helpMenu);
helpMenu.add(helpAction);
helpMenu.add(aboutAction);
}



/**//* Menu: View */

private void createViewMenu(IMenuManager menuBar)
{
// final IPreferenceScope preferences = Activator.getDefault().getPreferenceStore();

MenuManager viewMenu = new MenuManager("查看(&V)", M_VIEW);
viewMenu.setRemoveAllWhenShown(true);
menuBar.add(viewMenu);


/**//* Add dummy action to show the top level menu */

viewMenu.add(new Action("")
{
@Override

public void run()
{}
});


/**//* Build Menu dynamically */

viewMenu.addMenuListener(new IMenuListener()
{

public void menuAboutToShow(IMenuManager manager)
{
manager.add(new GroupMarker(M_VIEW_START));


/**//* Toggle State of Toolbar Visibility */

manager.add(new Action("工具栏", IAction.AS_CHECK_BOX)
{
@Override

public void run()
{
ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.WorkbenchWindowAdvisor;
boolean isToolBarVisible = preferences.getBoolean(DefaultPreferences.SHOW_TOOLBAR);
configurer.setToolBarVisible(!isToolBarVisible);
preferences.putValue(DefaultPreferences.SHOW_TOOLBAR, !isToolBarVisible + "");
}

@Override

public boolean isChecked()
{
return preferences.getBoolean(DefaultPreferences.SHOW_TOOLBAR);
}
});


/**//* Toggle State of Status Bar Visibility */

manager.add(new Action("状态栏", IAction.AS_CHECK_BOX)
{
@Override

public void run()
{
ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.WorkbenchWindowAdvisor;

boolean isStatusVisible = preferences.getBoolean(DefaultPreferences.SHOW_STATUS);
configurer.setStatusVisible(!isStatusVisible);
preferences.putValue(DefaultPreferences.SHOW_STATUS, !isStatusVisible + "");
}

@Override

public boolean isChecked()
{
return preferences.getBoolean(DefaultPreferences.SHOW_STATUS);
}
});


/**//* Toggle State of Bookmarks Visibility */
manager.add(new Separator());

manager.add(new Action("任务管理", IAction.AS_CHECK_BOX)
{
@Override

public void run()
{
IWorkbenchPage page = JDownUI.getPage();

if (page != null)
{
IViewPart mgrView = page.findView(TaskMgrView.ID);


/**//* Hide Bookmarks */
if (mgrView != null)
page.hideView(mgrView);


/**//* Show Bookmarks */

else
{

try
{
page.showView(TaskMgrView.ID);

} catch (PartInitException e)
{
Activator.getDefault().logError(e.getMessage(), e);
}
}
}
}

@Override

public boolean isChecked()
{
IWorkbenchPage page = JDownUI.getPage();
if (page != null)
return page.findView(TaskMgrView.ID) != null;
return false;
}
});

manager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
manager.add(new GroupMarker(M_VIEW_START));
}
});
}
无法就是从MenuManager创建几个Check Style的Action而已。主要看怎么实现这几个Action的主功能。以工具栏为例。
ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.WorkbenchWindowAdvisor;
boolean isToolBarVisible = preferences.getBoolean(DefaultPreferences.SHOW_TOOLBAR);
configurer.setToolBarVisible(!isToolBarVisible);
preferences.putValue(DefaultPreferences.SHOW_TOOLBAR, !isToolBarVisible + "");
首先要获取WorkbenchWindowAdvisor对象,隐藏的功能是在它方法中实现的,另外preferences是插件的首选项存储对象。把是否隐藏的状态持久化。我们再详看WorkbenchAdvisor的代码。

public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor
{

private static final String PERSPECTIVE_ID = "com.jdown.perspective";
public static ApplicationWorkbenchWindowAdvisor WorkbenchWindowAdvisor;

public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(

IWorkbenchWindowConfigurer configurer)
{
WorkbenchWindowAdvisor = new ApplicationWorkbenchWindowAdvisor(configurer);
return WorkbenchWindowAdvisor;
}


public String getInitialWindowPerspectiveId()
{
return PERSPECTIVE_ID;
}

}
稍微修改一下自动生成的代码就可以,它本身也是这么实现的。程序窗口的基本功能都是在ApplicationWorkbenchWindowAdvisor中配置的, 所以最终功能还是在它的上面实现的。

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
{


public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
{
super(configurer);
}

public ActionBarAdvisor createActionBarAdvisor(

IActionBarConfigurer configurer)
{
return new ApplicationActionBarAdvisor(configurer);
}


public void preWindowOpen()
{
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.setInitialSize(new Point(800, 600));
configurer.setShowCoolBar(true);
configurer.setShowStatusLine(true);
configurer.setTitle("JDown");
}

void setToolBarVisible(boolean visible)
{
getWindowConfigurer().setShowCoolBar(visible);


/**//* Hack: To avoid cheese, update Status Line Too */
boolean showsStatus = getWindowConfigurer().getShowStatusLine();
getWindowConfigurer().setShowStatusLine(!showsStatus);
getWindowConfigurer().setShowStatusLine(showsStatus);

getWindowConfigurer().getWindow().getShell().layout();
}


void setStatusVisible(boolean visible)
{
getWindowConfigurer().setShowStatusLine(visible);
getWindowConfigurer().setShowProgressIndicator(visible);


/**//* Hack: To avoid cheese, update ToolBar Too */
boolean showsToolBar = getWindowConfigurer().getShowCoolBar();
getWindowConfigurer().setShowCoolBar(!showsToolBar);
getWindowConfigurer().setShowCoolBar(showsToolBar);

getWindowConfigurer().getWindow().getShell().layout();
}
}

看到IWorkbenchWindowConfigurer其实才是问题的关键。限于篇幅原因,这里只做了一个简单的介绍,如果你有兴趣,可以详细看看它的源代码,还可以学到更多的技巧,当然不是唯一办法,只是学现成的比自己摸索要快。还有另一个功能点,就是工具栏的下拉菜单实现,毕竟看Eclipse的源代码太大,不容易理清楚关系,看它(RssOwl)就感觉清晰得多了。有时间再介绍一下。
慢慢研读,特别是core部分,肯定收获会不少!
刚进场的时候戏就落幕