Posted on 2008-07-31 15:13
寒武紀 閱讀(2086)
評論(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部分,肯定收獲會不少!
剛進場的時候戲就落幕