Posted on 2008-07-31 15:13
寒武紀(jì) 閱讀(2088)
評論(5) 編輯 收藏 所屬分類:
Eclipse
許久沒有弄RCP了,剛好近來閑暇一點(diǎn),找來個(gè)RSSOwl的源代碼看看,有點(diǎn)收獲。RssOwl非常出名,只是可能很多人不知道它是用Java做的。以前看過RssOwl第一版的源碼,沒有詳細(xì)研究,down下來之后放上公司的共享CVS服務(wù)器,倒是幾個(gè)同事饒有興趣地研究起來。第一個(gè)版本寫得較早,可能Eclipse的RCP框架都還沒有出來,所以全部采用的SWT/JFace實(shí)現(xiàn),主窗體就用的JFace里面的ApplicationWindow包裝起來的。粗看了一下,感覺代碼劃分和設(shè)計(jì)得不錯(cuò),把UI編碼的大部分重復(fù)功能都抽取出來,那時(shí)候做項(xiàng)目,就經(jīng)常從里面挖些代碼出來用。現(xiàn)在上它的主頁http://www.rssowl.org/,新設(shè)計(jì)的RssOwl 2 是基于RCP重構(gòu)的,已經(jīng)到了M8版本,主頁的download沒有直接的源代碼包下載,只提供了SVN庫,可以從里面check出來,地址是:https://rssowl.svn.sourceforge.net/svnroot/rssowl。拿出來后,總共是12個(gè)插件項(xiàng)目,相互關(guān)聯(lián)。示意圖如下:
從org.rssowl.build項(xiàng)目中的rssowl.product啟動(dòng)該RCP程序。可以預(yù)覽到全部界面。看一張預(yù)覽圖。

非常漂亮,具體功能可以自己感受一下。
主要的代碼都集中中org.rssowl.ui和org.rssowl.core二個(gè)插件,看標(biāo)題就明白是什么意思,它本身的存儲(chǔ)采用的是db4o,看來還是比較前衛(wèi)哦。上面的主菜單中有一個(gè)view,也就是我們常在IE外殼等上面看到的“查看”菜單,里面有,“工具欄,側(cè)邊欄,狀態(tài)欄”等等這些,可以隱藏或是顯示,菜單項(xiàng)是check風(fēng)格的。由于現(xiàn)在RssOwl 2仍處于Milestone階段,所以很多代碼仍是internal包里面的,以后肯定會(huì)慢慢變成公開的,做法和Eclpise如出一轍。
看一下org.rssowl.ui里面的代碼,下面這幾個(gè)非常熟悉的類。

菜單的設(shè)置就在ApplicationActionBarAdvisor.java類里面。為了簡單起見,我把它的代碼抽取出來,重新修改了一部分。如下:
@Override

protected void fillMenuBar(IMenuManager menuBar)
{
//
創(chuàng)建其它菜單
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("狀態(tài)欄", 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("任務(wù)管理", 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創(chuàng)建幾個(gè)Check Style的Action而已。主要看怎么實(shí)現(xiàn)這幾個(gè)Action的主功能。以工具欄為例。
ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.WorkbenchWindowAdvisor;
boolean isToolBarVisible = preferences.getBoolean(DefaultPreferences.SHOW_TOOLBAR);
configurer.setToolBarVisible(!isToolBarVisible);
preferences.putValue(DefaultPreferences.SHOW_TOOLBAR, !isToolBarVisible + "");
首先要獲取WorkbenchWindowAdvisor對象,隱藏的功能是在它方法中實(shí)現(xiàn)的,另外preferences是插件的首選項(xiàng)存儲(chǔ)對象。把是否隱藏的狀態(tài)持久化。我們再詳看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;
}

}
稍微修改一下自動(dòng)生成的代碼就可以,它本身也是這么實(shí)現(xiàn)的。程序窗口的基本功能都是在ApplicationWorkbenchWindowAdvisor中配置的, 所以最終功能還是在它的上面實(shí)現(xiàn)的。

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其實(shí)才是問題的關(guān)鍵。限于篇幅原因,這里只做了一個(gè)簡單的介紹,如果你有興趣,可以詳細(xì)看看它的源代碼,還可以學(xué)到更多的技巧,當(dāng)然不是唯一辦法,只是學(xué)現(xiàn)成的比自己摸索要快。還有另一個(gè)功能點(diǎn),就是工具欄的下拉菜單實(shí)現(xiàn),畢竟看Eclipse的源代碼太大,不容易理清楚關(guān)系,看它(RssOwl)就感覺清晰得多了。有時(shí)間再介紹一下。
慢慢研讀,特別是core部分,肯定收獲會(huì)不少!
剛進(jìn)場的時(shí)候戲就落幕