最近做个IDE的项目,要将文本编辑器和机遇gef的图形编辑器集成为Multipage编辑器,单独两个编辑器各自运行都是没有问题的,可是集成为一个Multipage编辑器就需要考虑很多编辑器之间同步的问题,要考虑的主要有:
1. Outline切换
2. 属性页切换
3. 文本/图形修改同步
4. ActionBar Contributor切换
本文主要讨论如何对OutlinePage进行同步,做到切换页面时outlinePage同步切换。
基本想法是这样的:(代码逻辑参考了一个叫StrutsIDE的开源插件)
通常outlinepage实例是通过getAdater方法返回的,在multipage编辑器中也是一样的,只是在切换不同tab的时候outlinepage也需要变化,因此,在MultipageEditor的pageChange方法中加入outlinepage切换代码。更具体一点的做法就是自己写一个外壳OutlinePage,当切换Multipage不同的编辑器时嵌入不同的outlinePage。请看定制的Outlinepage代码:
public class MultiPageEditorOutlinePage extends Page implements IContentOutlinePage {
private IContentOutlinePage activePage;
private IEditorPart activeEditor;
private Composite control;
/**
* Set the active editor.
* This outline page shows the outline which is provided by given editor.
*
* @param editor the active editor
*/
public void setActiveEditor(IEditorPart editor){
if(activePage!=null && activePage.getControl() != null){
activePage.getControl().dispose();
}
this.activeEditor = editor;
activePage = (IContentOutlinePage)editor.getAdapter(IContentOutlinePage.class);
if(control!=null){
if(activePage!=null){
initActivePage();
activePage.createControl(control);
getSite().getActionBars().updateActionBars();
control.layout();
}
}
}
public void createControl(Composite parent) {
control = new Composite(parent, SWT.NULL);
control.setLayout(new FillLayout());
if(activePage!=null){
initActivePage();
activePage.createControl(control);
}
}
/**
* Initializes the active outline page.
*/
private void initActivePage(){
getSite().getActionBars().getToolBarManager().removeAll();
getSite().getActionBars().getMenuManager().removeAll();
if(activePage instanceof IPageBookViewPage){
IPageBookViewPage pageBook = (IPageBookViewPage)activePage;
if(pageBook.getSite()==null){
try {
pageBook.init(getSite());
} catch(PartInitException ex){
ex.printStackTrace();
}
}
}
}
public Control getControl() {
/*if(activePage!=null){
activePage.getControl();
}*/
return control;
}
public void setFocus() {
if(activePage!=null){
activePage.setFocus();
}
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
if(activePage != null) {
activePage.addSelectionChangedListener(listener);
}
}
public ISelection getSelection() {
if(activePage!=null){
return activePage.getSelection();
}
return null;
}
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
if(activePage != null) {
activePage.removeSelectionChangedListener(listener);
}
}
public void setSelection(ISelection selection) {
if(activePage!=null){
activePage.setSelection(selection);
}
}
public IContentOutlinePage getActivePage() {
return activePage;
}
public IEditorPart getActiveEditor() {
return activeEditor;
}
}
KULMultiPageEditorOutlinePage集成Page,实现IContentOutlinePage接口,其中
public void setActiveEditor(IEditorPart editor){
....
}
方法就是供外部调用切换OutlinePage的主要接口,做的就是拿到当前编辑器的实例,调用当前编辑器的getAdator方法拿到outlinepage实例,在创建当前编辑器的outlinepage控件。上面的方法在MultipageEditor的pageChange方法中调用:
protected void pageChange(int newPageIndex) {
if(isDirty()){
if(newPageIndex==DIAGRAM_PAGE){
diagramEditor.flushCommandStack();
syncEditors(XML_PAGE);
} else if(newPageIndex==XML_PAGE){
syncEditors(DIAGRAM_PAGE);
}
}
super.pageChange(newPageIndex);
// enable or disable preview view when page change
handlePageChange(newPageIndex);
outlinePage.setActiveEditor(getEditor(newPageIndex));
propertySheetPage.setActiveEditor(getEditor(newPageIndex));
}
请看
outlinePage.setActiveEditor(getEditor(newPageIndex));
这句代码,就是告诉MultipageOutlinePage这个外壳,更换里面的内容。
通过以上方法,基本上可以做到切换不同编辑器outlinepage的同步变化,当然也有一点小问题,比如选中编辑器中的某个模型,outlinepage中对应的元素默认不会被选中,反过来倒是可以,等等。还需要进一步调试。