Действие 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();

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

Какие-либо предложения?


person Simone Rondelli    schedule 22.08.2013    source источник


Ответы (1)


Я нашел решение здесь:

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() в Capability, а не в Node, потому что Capability имеет включенное свойство:

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