ActionSet中Action的可用性(Enabled)

这里我想说的ActionSet是plugin.xml里面配置出来的ActionSet, 不是你在程序里面声明的.
程序里面声明的有setEnabled()方法, 简单的很.

举个例子, 在Navigator里面你选中一个Package或者Java文件, File菜单里面的rename变成可以用的, 而你选中JRE System Libaray这个节点, rename菜单就不能用了. 这就是这个菜单是和Navigator的选择相关的.

配置出来的Action必须实现IWorkbenchWindowActionDelegate接口, 里面有个selectionChanged(IAction, Selction)方法需要实现. 就是他了, 如下:
public   void  selectionChanged(IAction action, ISelection selection)  {
   
if (selection.isEmpty()) {
     action.setEnabled(
false);
   }
 else {
      IStructuredSelection iss 
= (IStructuredSelection)selection;
      Object obj 
= iss.getFirstElement();
     
if (obj instanceof TypeA) {
       action.setEnabled(
true);
     }
 else {
       action.setEnabled(
false);
     }

   }

}
TypeA是指你需要让Action可用的类型. 那么这个方法又是谁来调用呢?

具体的调用逻辑我不想多说了, 只想说你怎么可以让他动起来, 其实非常简单, 一句话的事情.
比如你自己有一个View, 里面是一个TreeViewer, TreeViewer是一个SelectionProvider, 于是在createPartControl()里面写上这么一句getSite().setSelectionProvider(viewer);, 哈哈, 万事大吉, 现在viewer的selection变化你已经可以在action里面监听到了, 是不是够简单?

另外一个要求, 注意File的Save菜单, 他是控制EditorPart和那些可以保存的ViewPart的. 如果当前EditorPart已经被更改, 那么他就可以用, 否则不行. 那么他是怎么实现的呢?
看看ActionFactory.SAVE. 一路摸上去, 会发现什么呢? 一串类, 分别是SaveAction, BaseSaveAction, ActiveEditorAction, PageEventAction, PartEventAction可惜的是, 他是从Action继承下来的, 配置的是IWorkbenchWindowActionDelegate, 他不是Action, 而你把他写成Action也毫无意义, 因为真正使用的Action是从这个IWorkbenchWindowActionDelegate创建出来的, 和他是不是Action没有什么关系.
所以, 我们需要重写一些东西.
首先写个PartEventActionDelegate, 实现和PartEventAction一摸一样, 不过构造就不需要了, 因为delegate的这部分内容都在plugin.xml里面呢, 如下
import  org.eclipse.ui.IPartListener;
import  org.eclipse.ui.IWorkbenchPart;
import  org.eclipse.ui.IWorkbenchWindowActionDelegate;

/**
 * 
@author Administrator
 * 
 
*/

public   abstract   class  PartEventActionDelegate  implements
        IWorkbenchWindowActionDelegate, IPartListener 
{

    
/**
     * The active part, or <code>null</code> if none.
     
*/

    
private IWorkbenchPart activePart;

    
/**
     * Returns the currently active part in the workbench.
     * 
     * 
@return currently active part in the workbench, or <code>null</code> if
     *         none
     
*/

    
public IWorkbenchPart getActivePart() {
        
return activePart;
    }


    
/**
     * The <code>PartEventAction</code> implementation of this
     * <code>IPartListener</code> method records that the given part is
     * active. Subclasses may extend this method if action availability has to
     * be recalculated.
     
*/

    
public void partActivated(IWorkbenchPart part) {
        activePart 
= part;
    }


    
/**
     * The <code>PartEventAction</code> implementation of this
     * <code>IPartListener</code> method does nothing. Subclasses should
     * extend this method if action availability has to be recalculated.
     
*/

    
public void partBroughtToTop(IWorkbenchPart part) {
        
// do nothing
    }


    
/**
     * The <code>PartEventAction</code> implementation of this
     * <code>IPartListener</code> method clears the active part if it just
     * closed. Subclasses may extend this method if action availability has to
     * be recalculated.
     
*/

    
public void partClosed(IWorkbenchPart part) {
        
if (part == activePart) {
            activePart 
= null;
        }

    }


    
/**
     * The <code>PartEventAction</code> implementation of this
     * <code>IPartListener</code> method records that there is no active part.
     * Subclasses may extend this method if action availability has to be
     * recalculated.
     
*/

    
public void partDeactivated(IWorkbenchPart part) {
        activePart 
= null;
    }


    
/**
     * The <code>PartEventAction</code> implementation of this
     * <code>IPartListener</code> method does nothing. Subclasses should
     * extend this method if action availability has to be recalculated.
     
*/

    
public void partOpened(IWorkbenchPart part) {
        
// do nothing
    }

}

第二步, 写个PageEventActionDelegate
import  org.eclipse.ui.IPageListener;
import  org.eclipse.ui.IWorkbenchPage;
import  org.eclipse.ui.IWorkbenchWindow;
import  org.eclipse.ui.actions.PartEventActionDelegate;

/**
 * 
@author Administrator
 * 
 
*/

public   abstract   class  PageEventActionDelegate  extends  PartEventActionDelegate
        
implements  IPageListener  {
    
/**
     * The active page, or <code>null</code> if none.
     
*/

    
private IWorkbenchPage activePage;

    
/**
     * The workbench window this action is registered with.
     
*/

    
private IWorkbenchWindow workbenchWindow;

    
/**
     * Returns the currently active page in the workbench window.
     * 
     * 
@return currently active page in the workbench window, or
     *         <code>null</code> in none
     
*/

    
public final IWorkbenchPage getActivePage() {
        
return activePage;
    }


    
/**
     * Returns the workbench window this action applies to.
     * 
     * 
@return the workbench window, or <code>null</code> if this action has
     *         been disposed
     
*/

    
public final IWorkbenchWindow getWorkbenchWindow() {
        
return workbenchWindow;
    }


    
/**
     * The <code>PageEventAction</code> implementation of this
     * <code>IPageListener</code> method records that the given page is
     * active. Subclasses may extend this method if action availability has to
     * be recalculated.
     
*/

    
public void pageActivated(IWorkbenchPage page) {
        
this.activePage = page;
    }


    
/**
     * The <code>PageEventAction</code> implementation of this
     * <code>IPageListener</code> method clears the active page if it just
     * closed. Subclasses may extend this method if action availability has to
     * be recalculated.
     
*/

    
public void pageClosed(IWorkbenchPage page) {
        
if (page == activePage) {
            activePage 
= null;
        }

    }


    
/**
     * The <code>PageEventAction</code> implementation of this
     * <code>IPageListener</code> method does nothing. Subclasses should
     * extend this method if action availability has to be recalculated.
     
*/

    
public void pageOpened(IWorkbenchPage page) {
        
// do nothing
    }


    
/**
     * The <code>PageEventAction</code> implementation of this
     * <code>ActionFactory.IWorkbenchAction</code> method deregisters the part
     * and page listener adding by the constructor. Subclasses should extend
     * this method to do additional cleanup.
     * 
     * 
@since 3.0
     
*/

    
public void dispose() {
        
if (workbenchWindow == null{
            
// action has already been disposed
            return;
        }

        workbenchWindow.removePageListener(
this);
        workbenchWindow.getPartService().removePartListener(
this);
        workbenchWindow 
= null;
    }


    
/**
     * 
     
*/

    
public void init(IWorkbenchWindow window) {
        
if (window == null{
            
throw new IllegalArgumentException();
        }

        
this.workbenchWindow = window;
        
this.activePage = window.getActivePage();
        
this.workbenchWindow.addPageListener(this);
        
this.workbenchWindow.getPartService().addPartListener(this);
    }

}

这个有点小小的改动, 就是把构造里面的东西挪到init()方法里了.
最后写个ActiveEditorActionDelegate, 如下
import  org.eclipse.jface.action.IAction;
import  org.eclipse.jface.viewers.ISelection;
import  org.eclipse.ui.IEditorPart;
import  org.eclipse.ui.IWorkbenchPage;
import  org.eclipse.ui.IWorkbenchPart;
import  org.eclipse.ui.internal.registry.IActionSet;

/**
 * 
@author Administrator
 * 
 
*/

public   abstract   class  ActiveEditorActionDelegate  extends
        PageEventActionDelegate 
{

    
private IEditorPart activeEditor;

    
/**
     * Notification that the active editor tracked by the action is being
     * activated.
     * 
     * Subclasses may override.
     
*/

    
protected void editorActivated(IEditorPart part) {
    }


    
/**
     * Notification that the active editor tracked by the action is being
     * deactivated.
     * 
     * Subclasses may override.
     
*/

    
protected void editorDeactivated(IEditorPart part) {
    }


    
/**
     * Return the active editor
     * 
     * 
@return the page's active editor, and <code>null</code> if no active
     *         editor or no active page.
     
*/

    
public final IEditorPart getActiveEditor() {
        
return activeEditor;
    }


    
/*
     * (non-Javadoc) Method declared on PageEventAction.
     
*/

    
public void pageActivated(IWorkbenchPage page) {
        
super.pageActivated(page);
        updateActiveEditor();
        updateState();
    }


    
/*
     * (non-Javadoc) Method declared on PageEventAction.
     
*/

    
public void pageClosed(IWorkbenchPage page) {
        
super.pageClosed(page);
        updateActiveEditor();
        updateState();
    }


    
/*
     * (non-Javadoc) Method declared on PartEventAction.
     
*/

    
public void partActivated(IWorkbenchPart part) {
        
super.partActivated(part);
        
if (part instanceof IEditorPart) {
            updateActiveEditor();
            updateState();
        }

    }


    
/*
     * (non-Javadoc) Method declared on PartEventAction.
     
*/

    
public void partBroughtToTop(IWorkbenchPart part) {
        
super.partBroughtToTop(part);
        
if (part instanceof IEditorPart) {
            updateActiveEditor();
            updateState();
        }

    }


    
/*
     * (non-Javadoc) Method declared on PartEventAction.
     
*/

    
public void partClosed(IWorkbenchPart part) {
        
super.partClosed(part);
        
if (part instanceof IEditorPart) {
            updateActiveEditor();
            updateState();
        }

    }


    
/*
     * (non-Javadoc) Method declared on PartEventAction.
     
*/

    
public void partDeactivated(IWorkbenchPart part) {
        
super.partDeactivated(part);
        
if (part instanceof IEditorPart) {
            updateActiveEditor();
            updateState();
        }

    }


    
/**
     * Set the active editor
     
*/

    
private void setActiveEditor(IEditorPart part) {
        
if (activeEditor == part) {
            
return;
        }

        
if (activeEditor != null{
            editorDeactivated(activeEditor);
        }

        activeEditor 
= part;
        
if (activeEditor != null{
            editorActivated(activeEditor);
        }

    }


    
/**
     * Update the active editor based on the current active page.
     
*/

    
private void updateActiveEditor() {
        
if (getActivePage() == null{
            setActiveEditor(
null);
        }
 else {
            setActiveEditor(getActivePage().getActiveEditor());
        }

    }


    
/**
     * Update the state of the action. By default, the action is enabled if
     * there is an active editor.
     * 
     * Subclasses may override or extend this method.
     
*/

    
protected void updateState() {
        ActionPresentation ap 
= ((WorkbenchWindow) getWorkbenchWindow())
                .getActionPresentation();
        IActionSet[] sets 
= ap.getActionSets();
        
if (sets != null{
            
for (IActionSet set : sets) {
                PluginActionSet pas 
= (PluginActionSet) set;
                IAction[] actions 
= pas.getPluginActions();
                
if (actions != null{
                    
for (IAction action : actions) {
                        
if (action.getId().equals(getId())) {
                            action.setEnabled(getActiveEditor() 
!= null);
                            
return;
                        }

                    }

                }

            }

        }

    }


    
protected abstract String getId();

    
private boolean first = true;

    
public void selectionChanged(IAction action, ISelection selection) {
        
if (first) {
            first 
= false;
            action.setEnabled(
false);
        }

    }

}

有点变化, 首先是updateState方法, 变了很多. 主要是找到由自己创建的那个Action, 我比较笨, 没有找到更好的方法. getId()返回的是你这个Action在plugin.xml里面声明的id.
然后需要解决的问题就是如果让他一开始是disable的, 我想了几个办法都不行, 唯一的办法就是重写selectionChanged方法, 只调用一次, 无论如何,将其设置成disabled. 但是这个方式可能在你的RCP里面行不通, 要具体情况具体分析.
ActiveEditorAction里面是构造的时候就updateState, 但是这里不行. 为什么不行? 因为init的时候还没有构造出Action, 也就是通过我的方法你是那不到这个Action的, 也就是说没办法设置成disabled. 如此而已.
这个是个问题, 希望哪位达人看到这篇文章, 指正一下.

接下来的事情我就不多说了, 顺着BaseSaveAction和SaveAction看下去就可以了, 呵呵, 简单的很啊.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值