Retarget

 

RetargetAction是eclipse里非常好的action机制:可以起到非常好的动态绑定功能:

       比如保存按钮,当打开不同编辑器时,会执行对应编辑器的保存action.这样就达到了完美共享,动态绑定的作用,这个动态绑定主要是通过监听活动part来达到的。

要使用retarget,必须有两样东西:一是一个retarget的实例,一个是真正的action.

下面我们以一个创建deletaction来说明retarget的使用及机制:

一:单独retarget方式:

1. 创建DeleteRetargetAction类

public class DeleteRetargetAction extends RetargetAction {
 public DeleteRetargetAction() {
  super(IWorkbenchActionConstants.Delete, "删除(&D)");
  this.setActionDefinitionId("net.foreworld.rss2.bindings.command.delete");
  this.setImageDescriptor(Activator.getImageDescriptor("icons/QuickReader_140.gif"));
 }
}

2. ApplicationActionBarAdvisor.makeActions() 中添加

this.deleteRetargetAction = new DeleteRetargetAction();
this.register(this.deleteRetargetAction);
window.getPartService().addPartListener(this.deleteRetargetAction);

//这个的作用就是当有part激活时会调用用partActivated,从而来将DeleteRetargetAction和deleteAction绑定的

 

public void partActivated(IWorkbenchPart part) {

        super.partActivated(part);

        IWorkbenchPartSite site = part.getSite();

        SubActionBars bars = (SubActionBars) ((PartSite) site).getActionBars();

        bars.addPropertyChangeListener(propertyChangeListener);

        setActionHandler(bars.getGlobalActionHandler(getId()));

    }

当一个part(viewpart或editorpart)激活时,就会执行deleteRetargetAction的partActivated

这样这个retarget就和具体的action绑定了,即将将action赋给retarget的handle.

 

protected void setActionHandler(IAction newHandler) {

        // Optimize.

        if (newHandler == handler) {

           return;

       }

 

        // Clear old action.

        if (handler != null) {

            handler.removePropertyChangeListener(propertyChangeListener);

            handler = null;

        }

 // Set new action.

       IAction oldHandler = handler;

        handler = newHandler;

        if (handler == null) {

            setEnabled(false);

            if (getStyle() == AS_CHECK_BOX || getStyle() == AS_RADIO_BUTTON) {

                setChecked(false);

            }

        } else {

            setEnabled(handler.isEnabled());

            if (getStyle() == AS_CHECK_BOX || getStyle() == AS_RADIO_BUTTON) {

                setChecked(handler.isChecked());

            }

            handler.addPropertyChangeListener(propertyChangeListener);

//这个用来aciton控制retarget的,比如enable等属性,当action setenable时就会调用

        }

      

       // Notify listeners that the handler has changed.

        firePropertyChange(IHandlerAttributes.ATTRIBUTE_HANDLED, oldHandler,

                newHandler);

}

 

,当action setenabled时就会调用        

public void setEnabled(boolean enabled) {

           if (enabled != this.enabled) {

           Boolean oldVal = this.enabled ? Boolean.TRUE : Boolean.FALSE;

           Boolean newVal = enabled ? Boolean.TRUE : Boolean.FALSE;

           this.enabled = enabled;

           firePropertyChange(ENABLED, oldVal, newVal);

            }

 

下面是retarget的

private IPropertyChangeListener propertyChangeListener = new IPropertyChangeListener() {

        public void propertyChange(PropertyChangeEvent event) {

            RetargetAction.this.propagateChange(event);

        }

    };

 

protected void propagateChange(PropertyChangeEvent event) {

        if (event.getProperty().equals(IAction.ENABLED)) {

            Boolean bool = (Boolean) event.getNewValue();

            setEnabled(bool.booleanValue());

        } else if (event.getProperty().equals(IAction.CHECKED)) {

            Boolean bool = (Boolean) event.getNewValue();

            setChecked(bool.booleanValue());

        } else if (event.getProperty().equals(SubActionBars.P_ACTION_HANDLERS)) {

            if (event.getSource() instanceof IActionBars) {

                IActionBars bars = (IActionBars) event.getSource();

                setActionHandler(bars.getGlobalActionHandler(getId()));

            }

        }

    }

3. 在你的view中添加钩子

actionBars.setGlobalActionHandler(IWorkbenchActionConstants.Delete, this.deleteAction);

用getActionBars. setGlobalActionHandler().

这个就是刚才bars.getGlobalActionHandler的内容提供商。

 

二:在Editor里,以ActionBarContribut的形式:

     public class DiagramActionBarContributor extends ActionBarContributor {

 

 

    protected void buildActions() {

        addRetargetAction(new DeleteRetargetAction());

      

    }

    protected void declareGlobalActionKeys() {

        // TODO Auto-generated method stub

 

    }

public void contributeToToolBar(IToolBarManager toolBarManager) {

        toolBarManager.add(getActionRegistry().getAction(IWorkbenchActionConstants.Delete));

//这个返回就是上面函数添加的retarget.

       

    }   

public void contributeToToolBar(IToolBarManager toolBarManager) {

        toolBarManager.add(getActionRegistry().getAction(IWorkbenchActionConstants.Delete));

       

}

上面的addRetargetAction就实现了1中window.getPartService().addPartListener(this.deleteRetargetAction);效果:

 protected void addRetargetAction(RetargetAction action) {

    addAction(action);

    retargetActions.add(action);

    getPage().addPartListener(action);

    addGlobalActionKey(action.getId());

}

然后在editor里添加真正的deleteAction,就达到remote action的作用了,一般通过setAction函数,这个函数后,然后就可以通过getAction(string id)获得这个action.

也就是真正的action是通过setAction()来注册到editor中,然后editor active时又会将这些注册到bars.

所有的retarget都是靠part激活时的GetGlobalActionHandler来绑定:

需要将其用到的retargetaciton id对应的action也放到part的GlobalActionHandler里。

这是在绑定contributeclass和part时实现的,当绑定时,part会调用

public void setActiveEditor(IEditorPart editor) {

    ActionRegistry registry = (ActionRegistry)editor.getAdapter(ActionRegistry.class);

    IActionBars bars = getActionBars();

    for (int i = 0; i < globalActionKeys.size(); i++) {

       String id = (String)globalActionKeys.get(i);

       bars.setGlobalActionHandler(id, registry.getAction(id));

    }

}

这样就把在actionbarContributor里通过setAction函数添加的action放到editpart的GlobalActionHandler,从而可被retarget绑定.

阅读更多

扫码向博主提问

刚刚下班

非学,无以致疑;非问,无以广识
  • 擅长领域:
  • 数据分析
  • 机器学习
  • 数据挖掘
去开通我的Chat快问
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页