2013-08-22 1 views
0

Я пытаюсь реализовать действие, которое включено или отключено (в верхнем меню приложения и во всплывающем меню, щелкнув правой кнопкой мыши на узле) в зависимости от текущего состояния узла/узлов.Действие Netbeans разрешено в зависимости от состояния узла

@ActionID(
     category = "Application", 
     id = "it.cre.app.tree.actions.ShowEventsAction") 
@ActionRegistration(
     iconBase = "it/cre/app/tree/actions/show.png", 
     displayName = "#CTL_ShowAction") 
@ActionReferences({ 
    @ActionReference(path = "Menu/Edit", position = 100), 
    @ActionReference(path = "Toolbars/File", position = 300), 
    @ActionReference(path = "Application/edit", position = 0)}) 
@NbBundle.Messages("CTL_ShowAction=Show Events") 
public class ShowEventsAction implements ActionListener { 

    private ShowAuditEventsCapability showAuditEventsCapability; 

    public ShowEventsAction(ShowAuditEventsCapability context) { 
     showAuditEventsCapability = context; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     if (showAuditEventsCapability != null) { 
      doSomething(); 
     } 
    } 
} 

Например: Это действие, по умолчанию, включается только тогда, когда один узел выбран в противном случае отключается (видимый, но отключен). Я хочу такое же поведение, но также и на основе состояния выбранного узла.

Все мои узлы реализует свой интерфейс:

public interface INode { 
    //obviously the state of the node could change at runtime 
    public boolean someState(); 
} 

так я могу получить состояние узла в моем действии каким-то образом, как это:

boolean state = Utilities.actionsGlobalContext().lookup(INode.class).someState(); 

Как можно использовать предыдущий фрагмент кода для включения/отключения действия, когда я выбираю узел, таким же образом, когда это действие отключено, когда выбрано несколько узлов?

Любые предложения?

ответ

0

Я нашел решение here:

public class ShowEventsAction extends AbstractAction implements LookupListener, ContextAwareAction { 

    private Lookup context; 
    Lookup.Result<ShowAuditEventsCapability> lkpInfo; 

    public ShowEventsAction() { 
     this(Utilities.actionsGlobalContext()); 
    } 

    public ShowEventsAction(Lookup context) { 
     super("Show Audit Events", ImageUtilities.loadImageIcon("it/cre/myapp/audittree/actions/show.png", false)); 
     this.context = context; 
    } 

    void init() { 
     assert SwingUtilities.isEventDispatchThread() : "this shall be called just from AWT thread"; 

     if (lkpInfo != null) { 
      return; 
     } 

     //The thing we want to listen for the presence or absence of 
     //on the global selection 
     lkpInfo = context.lookupResult(ShowAuditEventsCapability.class); 
     lkpInfo.addLookupListener(this); 
     resultChanged(null); 
    } 

    @Override 
    public boolean isEnabled() { 
     init(); 
     return super.isEnabled(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     init(); 
     for (ShowAuditEventsCapability showAuditEventsCapability : lkpInfo.allInstances()) { 
      showAuditEventsCapability.doSomething(); 
     } 
    } 

    @Override 
    public void resultChanged(LookupEvent ev) { 
     int selected = lkpInfo.allInstances().size(); 

     if (selected == 0) { 
      setEnabled(false); 
      return; 
     } 

     for (EasyDbNode node : Utilities.actionsGlobalContext().lookupAll(INode.class)) { 
      if (!node.isEnabled()) { 
       setEnabled(false); 
       return; 
      } 
     } 
     setEnabled(true); 
    } 

    @Override 
    public Action createContextAwareInstance(Lookup actionContext) { 
     return new ShowEventsAction(context); 
    } 
} 

Это работает! Но я считаю, что лучше всего использовать метод isEnabled() в возможности, а не в узле, потому что это способность, которая имеет свойство:

public void resultChanged(LookupEvent ev) { 
    for(ShowAuditEventsCapability capability : lkpInfo.allInstances()) { 
     if(!capability.isEnabled()) { 
      setEnabled(false); 
      return; 
     } 
    } 
    setEnabled(true); 
}