package Templates.API_Support.Actions_API;

import java.awt.event.ActionEvent;
import java.util.*;
import javax.swing.JMenuItem;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.openide.awt.Actions;
import org.openide.awt.JInlineMenu;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.*;

/** Action that displays a submenu when presented in a menu or popup.
 *
 * @author __USER__
 */
public class __Sample_submenu__Action extends SystemAction implements Presenter.Menu, Presenter.Popup {

    public void actionPerformed(ActionEvent ev) {
        // do nothing -- should never be called
    }

    public String getName() {
        return NbBundle.getMessage(__NAME__.class, "LBL_Action");
    }

    protected String iconResource() {
        return "__PACKAGE_AND_NAME_SLASHES__Icon.gif";
    }

    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
        // If you will provide context help then use:
        // return new HelpCtx(__NAME__.class);
    }

    /** Perform extra initialization of this action's singleton.
     * PLEASE do not use constructors for this purpose!
    protected void initialize() {
	super.initialize();
	putProperty("someProp", value);
    }
    */

    public JMenuItem getMenuPresenter() {
        if (anythingToDisplay())
            // Could also try to share a common model, if it is hard to compute.
            return new SpecialSubMenu(this, new ActSubMenuModel(), false);
        else
            return new JInlineMenu(); // do not display at all
    }

    public JMenuItem getPopupPresenter() {
        if (anythingToDisplay())
            return new SpecialSubMenu(this, new ActSubMenuModel(), true);
        else
            return new JInlineMenu(); // do not display at all
    }

    private boolean anythingToDisplay() {
        // test whether or not there will be anything to display in the submenu
        // if false, whole item will just disappear
        return true;
    }

    /** Special submenu which notifies model when it is added as a component.
    */
    private static final class SpecialSubMenu extends Actions.SubMenu {

        private final ActSubMenuModel model;

        SpecialSubMenu(SystemAction action, ActSubMenuModel model, boolean popup) {
            super(action, model, popup);
            this.model = model;
        }

        public void addNotify() {
            model.addNotify();
            super.addNotify();
        }

        // removeNotify not useful--might be called before action is invoked

    }

    /** Model to use for the submenu.
    */
    private static final class ActSubMenuModel implements Actions.SubMenuModel {

        private List<String> displayNames;
        private List<Object> associatedInfo;

        private Set<ChangeListener> listeners = new HashSet<ChangeListener>();

        public int getCount() {
            return displayNames.size();
        }

        public String getLabel(int index) {
            return displayNames.get(index);
        }

        public HelpCtx getHelpCtx(int index) {
            return HelpCtx.DEFAULT_HELP; // could add something special here, or new HelpCtx(__NAME__.class)
        }

        public void performActionAt(int index) {
            Object info = associatedInfo.get(index);
            // do something with it
        }

        public synchronized void addChangeListener(ChangeListener l) {
            listeners.add(l);
        }

        public synchronized void removeChangeListener(ChangeListener l) {
            listeners.remove(l);
        }

        /** You may use this is you have attached other listeners to things that will affect displayNames, for example. */
        private synchronized void fireStateChanged() {
            if (listeners.size() == 0) return;
            ChangeEvent ev = new ChangeEvent(this);
            for (ChangeListener listener : listeners) {
                listener.stateChanged(ev);
            }
        }

        void addNotify() {
            // create displayNames and associatedInfo somehow
        }

    }

}
