浅谈MultiPageEditorActionBarContributor

来源:互联网 发布:网络尖兵软件下载 编辑:程序博客网 时间:2024/05/18 12:38
MultiPageEditorActionBarContributor是多页编辑器(MultiPageEditorPart)的EditorActionBarContributor实现。

最近在重构一个GEF项目,将之前的单页编辑器(EditorPart)重构为了多页编辑器(MultiPageEditorPart),发现在切换页面过程中之前的一系列
Retarget Action(cut,delete,paste等)都失效了。
debug出了问题的所在。由于原来是单页编辑器,EditorActionBarContributor是继承自GEF的ActionBarContributor类。由于是多页,在切换过程中,
自然就会出现问题。

多页编辑器的EditorActionBarContributor应该实现MultiPageEditorActionBarContributor,它继承自EditorActionBarContributor。
核心是要实现抽象方法setActivePage(IEditorPart activeEditor)。

继承使用见样学样法则,看看PDE是怎样实现的:
public class PDEFormEditorContributor extends MultiPageEditorActionBarContributor {

 protected PDEFormEditor fEditor;

 protected IFormPage fPage;

 private SaveAction fSaveAction;

 protected RevertAction fRevertAction;

 private ClipboardAction fCutAction;

 private ClipboardAction fCopyAction;

 private ClipboardAction fPasteAction;

 private Hashtable fGlobalActions = new Hashtable();

 private ISharedImages fSharedImages;

 class GlobalAction extends Action implements IUpdate {
  private String id;

  public GlobalAction(String id) {
   this.id = id;
  }

  public void run() {
   fEditor.performGlobalAction(id);
   updateSelectableActions(fEditor.getSelection());
  }

  public void update() {
   getActionBars().updateActionBars();
  }
 }

 class ClipboardAction extends GlobalAction {
  public ClipboardAction(String id) {
   super(id);
   setEnabled(false);
  }

  public void selectionChanged(ISelection selection) {
  }

  public boolean isEditable() {
   if (fEditor == null)
    return false;
   IBaseModel model = fEditor.getAggregateModel();
   return model instanceof IEditable ? ((IEditable) model).isEditable() : false;
  }
 }

 class CutAction extends ClipboardAction {
  public CutAction() {
   super(ActionFactory.CUT.getId());
   setText(PDEUIMessages.EditorActions_cut);
   setImageDescriptor(getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
   setDisabledImageDescriptor(getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
   setActionDefinitionId("org.eclipse.ui.edit.cut"); //$NON-NLS-1$
  }

  public void selectionChanged(ISelection selection) {
   setEnabled(isEditable() && fEditor.canCut(selection));
  }
 }

 class CopyAction extends ClipboardAction {
  public CopyAction() {
   super(ActionFactory.COPY.getId());
   setText(PDEUIMessages.EditorActions_copy);
   setImageDescriptor(getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
   setDisabledImageDescriptor(getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
   setActionDefinitionId("org.eclipse.ui.edit.copy"); //$NON-NLS-1$
  }

  public void selectionChanged(ISelection selection) {
   setEnabled(fEditor.canCopy(selection));
  }
 }

 class PasteAction extends ClipboardAction {
  public PasteAction() {
   super(ActionFactory.PASTE.getId());
   setText(PDEUIMessages.EditorActions_paste);
   setImageDescriptor(getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));
   setDisabledImageDescriptor(getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED));
   setActionDefinitionId("org.eclipse.ui.edit.paste"); //$NON-NLS-1$
  }

  public void selectionChanged(ISelection selection) {
   setEnabled(isEditable() && fEditor.canPasteFromClipboard());
  }
 }

 class SaveAction extends Action implements IUpdate {
  public SaveAction() {
  }

  public void run() {
   if (fEditor != null)
    PDEPlugin.getActivePage().saveEditor(fEditor, false);
  }

  public void update() {
   setEnabled(fEditor != null ? fEditor.isDirty() : false);
  }
 }

 class RevertAction extends Action implements IUpdate {
  public RevertAction() {
  }

  public void run() {
   if (fEditor != null)
    fEditor.doRevert();
  }

  public void update() {
   setEnabled(fEditor != null ? fEditor.isDirty() : false);
  }
 }

 public PDEFormEditorContributor(String menuName) {
 }

 private void addGlobalAction(String id) {
  GlobalAction action = new GlobalAction(id);
  addGlobalAction(id, action);
 }

 private void addGlobalAction(String id, Action action) {
  fGlobalActions.put(id, action);
  getActionBars().setGlobalActionHandler(id, action);//关联Retarget Action
 }

 public void addClipboardActions(IMenuManager mng) {
  mng.add(fCutAction);
  mng.add(fCopyAction);
  mng.add(fPasteAction);
  mng.add(new Separator());
  mng.add(fRevertAction);
 }

 public void contextMenuAboutToShow(IMenuManager mng) {
  contextMenuAboutToShow(mng, true);
 }

 public void contextMenuAboutToShow(IMenuManager mng, boolean addClipboard) {
  if (fEditor != null)
   updateSelectableActions(fEditor.getSelection());
  if (addClipboard)
   addClipboardActions(mng);
  mng.add(fSaveAction);
 }
 
 public void contributeToMenu(IMenuManager mm) {
 }

 public void contributeToStatusLine(IStatusLineManager slm) {
 }

 public void contributeToToolBar(IToolBarManager tbm) {
 }

 public void contributeToCoolBar(ICoolBarManager cbm) {
 }

 public PDEFormEditor getEditor() {
  return fEditor;
 }

 public IAction getGlobalAction(String id) {
  return (IAction) fGlobalActions.get(id);
 }

 public IAction getSaveAction() {
  return fSaveAction;
 }

 public IAction getRevertAction() {
  return fRevertAction;
 }

 public IStatusLineManager getStatusLineManager() {
  return getActionBars().getStatusLineManager();
 }

 protected void makeActions() {
  // clipboard actions
  fCutAction = new CutAction();
  fCopyAction = new CopyAction();
  fPasteAction = new PasteAction();
  addGlobalAction(ActionFactory.CUT.getId(), fCutAction);//设置Retarget Action关联(hook)
  addGlobalAction(ActionFactory.COPY.getId(), fCopyAction);
  addGlobalAction(ActionFactory.PASTE.getId(), fPasteAction);
  addGlobalAction(ActionFactory.DELETE.getId());
  // undo/redo
  addGlobalAction(ActionFactory.UNDO.getId());
  addGlobalAction(ActionFactory.REDO.getId());
  // select/find
  addGlobalAction(ActionFactory.SELECT_ALL.getId());
  addGlobalAction(ActionFactory.FIND.getId());
  // bookmark
  addGlobalAction(IDEActionFactory.BOOKMARK.getId());
  // save/revert
  fSaveAction = new SaveAction();
  fSaveAction.setText(PDEUIMessages.EditorActions_save);
  fRevertAction = new RevertAction();
  fRevertAction.setText(PDEUIMessages.EditorActions_revert);
  addGlobalAction(ActionFactory.REVERT.getId(), fRevertAction);
 }

 public void setActiveEditor(IEditorPart targetEditor) {
  if (targetEditor instanceof PDESourcePage) {
   // Fixing the 'goto line' problem -
   // the action is thinking that source page
   // is a standalone editor and tries to activate it
   // #19361
   PDESourcePage page = (PDESourcePage) targetEditor;
   PDEPlugin.getActivePage().activate(page.getEditor());
   return;
  }
  if (!(targetEditor instanceof PDEFormEditor))
   return;

  fEditor = (PDEFormEditor) targetEditor;
  fEditor.updateUndo(getGlobalAction(ActionFactory.UNDO.getId()), getGlobalAction(ActionFactory.REDO.getId()));
  setActivePage(fEditor.getActiveEditor());
  updateSelectableActions(fEditor.getSelection());
 }

 //需要实现的抽象方法
 public void setActivePage(IEditorPart newEditor) {
  if (fEditor == null)
   return;
  IFormPage oldPage = fPage;
  fPage = fEditor.getActivePageInstance();
  if (fPage != null) {
   updateActions();
   if (oldPage != null && !oldPage.isEditor() && !fPage.isEditor()) {
    getActionBars().updateActionBars();//更新ActionBar
   }
  }
 }

 public void updateActions() {
  fSaveAction.update();
  fRevertAction.update();
 }

 public void updateSelectableActions(ISelection selection) {
  if (fEditor != null) {
   fCutAction.selectionChanged(selection);
   fCopyAction.selectionChanged(selection);
   fPasteAction.selectionChanged(selection);
  }
 }

 public IEditorActionBarContributor getSourceContributor() {
  return null;
 }

 public void init(IActionBars bars) {
  super.init(bars);
  makeActions();//初始化时,创建Actions
 }

 protected ISharedImages getSharedImages() {
  if (fSharedImages == null)
   fSharedImages = getPage().getWorkbenchWindow().getWorkbench().getSharedImages();
  return fSharedImages;
 }
}


再看一个多页编辑器向导模板中的实现:
我对其进行了一些改造。
public class MultiPageEditorContributor extends
  MultiPageEditorActionBarContributor {
 private IEditorPart activeEditorPart;
 private Action sampleAction;
 
 public MultiPageEditorContributor() {
  super();
  createActions();
 }

 /**
  * Returns the action registed with the given text editor.
  */
 protected IAction getAction(ITextEditor editor, String actionID) {
  return (editor == null ? null : editor.getAction(actionID));
 }

 //新添加的方法,在MyEditor中定义了一些Action
 protected IAction getAction2(MyEditor editor, String actionID) {
  return (editor == null ? null : editor.getAction(actionID));
 }

 // 主要看该方法
 public void setActivePage(IEditorPart part) {
  if (activeEditorPart == part)
   return;

  activeEditorPart = part;
  if (activeEditorPart instanceof TextEditor) {
   IActionBars actionBars = getActionBars();
   if (actionBars != null) {

    ITextEditor editor = (part instanceof ITextEditor) ? (ITextEditor) part
      : null;
    
    actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(),
      getAction(editor, ITextEditorActionConstants.CUT));//关联Retarget Action
      getAction(editor, ITextEditorActionConstants.FIND);
    actionBars.updateActionBars();
   }
  } else if(activeEditorPart instanceof MyEditor) {
   //下面改造的,这样当切换至MyEditor页面时,cut菜单的关联也有作用了
   IActionBars actionBars = getActionBars();
   if (actionBars != null) {
    MyEditor editor = (activeEditorPart instanceof MyEditor) ? (MyEditor) part
      : null;
    actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(),
      getAction2(editor, ITextEditorActionConstants.CUT));
    actionBars.updateActionBars();
   }
   
  }
 }

 private void createActions() {
  sampleAction = new Action() {
   public void run() {
    MessageDialog.openInformation(null, "Test Plug-in",
      "Sample Action Executed");
   }
  };
  sampleAction.setText("Sample Action");
  sampleAction.setToolTipText("Sample Action tool tip");
  sampleAction.setImageDescriptor(PlatformUI.getWorkbench()
    .getSharedImages().getImageDescriptor(
      IDE.SharedImages.IMG_OBJS_TASK_TSK));
 }

 //添加共享菜单
 public void contributeToMenu(IMenuManager manager) {
  IMenuManager menu = new MenuManager("编辑器贡献的菜单");
  manager.prependToGroup(IWorkbenchActionConstants.MB_ADDITIONS, menu);
  menu.add(sampleAction);
 }

 public void contributeToToolBar(IToolBarManager manager) {
  manager.add(new Separator());
  manager.add(sampleAction);
 }
}