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绑定.