/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2004 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */
package org.gnu.gtk;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.gnu.glib.EventMap;
import org.gnu.glib.GObject;
import org.gnu.glib.Handle;
import org.gnu.gtk.event.ActionEvent;
import org.gnu.gtk.event.ActionListener;

/**
 * An action which can be triggered by a menu or toolbar item.
 * 
 * <p>
 * Actions represent operations that the user can be perform, along with some
 * information how it should be presented in the interface. Each action provides
 * methods to create icons, menu items and toolbar items representing itself.
 * 
 * <p>
 * As well as the callback that is called when the action gets activated, the
 * following also gets associated with the action:
 * 
 * <p>
 * a name (not translated, for path lookup)
 * 
 * <p>
 * a label (translated, for display)
 * 
 * <p>
 * an accelerator
 * 
 * <p>
 * whether label indicates a stock id
 * 
 * <p>
 * a tooltip (optional, translated)
 * 
 * <p>
 * a toolbar label (optional, shorter than label)
 * 
 * <p>
 * The action will also have some state information:
 * 
 * <p>
 * visible (shown/hidden)
 * 
 * <p>
 * sensitive (enabled/disabled)
 * 
 * <p>
 * Apart from regular actions, there are {@link ToggleAction}, which can be
 * toggled between two states and {@link RadioAction}, of which only one in a
 * group can be in the "active" state. Other actions can be implemented as
 * {@link Action} subclasses.
 * 
 * <p>
 * Each action can have one or more proxy menu item, toolbar button or other
 * proxy widgets. Proxies mirror the state of the action (text label, tooltip,
 * icon, visible, sensitive, etc), and should change when the action's state
 * changes. When the proxy is activated, it should activate its action.
 *
 * @deprecated This class is part of the java-gnome 2.x family of libraries,
 *             which, due to their inefficiency and complexity, are no longer
 *             being maintained and have been abandoned by the java-gnome
 *             project. This class may in the future have an equivalent in
 *             java-gnome 4.0, try looking for
 *             <code>org.gnome.gtk.Action</code>.
 *             You should be aware that there is a considerably different API
 *             in the new library: the architecture is completely different
 *             and most notably internals are no longer exposed to public view.
 */

public class Action extends GObject {

    protected static EventMap evtMap = new EventMap();

    protected Vector actionListeners = null;

    /**
     * Construct a new Action object.
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public Action(String name, String label, String tooltip, String stockId) {
        super(gtk_action_new(name, label, tooltip, stockId));
    }

    // protected Action() {}

    Action(Handle handle) {
        super(handle);
    }

    /**
     * Internal static factory method to be used by Java-Gnome only.
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    static Action getAction(Handle handle) {
        if (handle == null)
            return null;

        Action action = (Action) getGObjectFromHandle(handle);
        if (action == null)
            action = new Action(handle);

        return action;
    }

    /**
     * Returns the name of the action.
     * 
     * @return the name of the action
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public String getName() {
        return gtk_action_get_name(getHandle());
    }

    /**
     * Emits the "activate" signal on the specified action, if it isn't
     * insensitive. This gets called by the proxy widgets when they get
     * activated.
     * 
     * It can also be used to manually activate an action.
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void activate() {
        gtk_action_activate(getHandle());
    }

    /**
     * This function is intended for use by action implementations to create
     * icons displayed in the proxy widgets.
     * 
     * @param iconSize
     *            the size of the icon that should be created
     * @return a widget that displays the icon for this action
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public Widget createIcon(IconSize iconSize) {
        return new Widget(gtk_action_create_icon(getHandle(), iconSize
                .getValue()));
    }

    /**
     * Creates a menu item widget that proxies for the given action.
     * 
     * @return a menu item connected to the action
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public Widget createMenuItem() {
        return new MenuItem(gtk_action_create_menu_item(getHandle()));
    }

    /**
     * Creates a toolbar item widget that proxies for the given action.
     * 
     * @return a toolbar item connected to the action
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public Widget createToolItem() {
        return new ToolItem(gtk_action_create_tool_item(getHandle()));
    }

    /**
     * Connects a widget to an action object as a proxy. Synchronises various
     * properties of the action with the widget (such as label text, icon,
     * tooltip, etc), and attaches a callback so that the action gets activated
     * when the proxy widget does.
     * 
     * If the widget is already connected to an action, it is disconnected
     * first.
     * 
     * @param proxy
     *            the proxy widget
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void connectProxy(Widget proxy) {
        gtk_action_connect_proxy(getHandle(), proxy.getHandle());
    }

    /**
     * Disconnects a proxy widget from an action. Does not destroy the widget,
     * however.
     * 
     * @param proxy
     *            the proxy widget
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void disconnectProxy(Widget proxy) {
        gtk_action_disconnect_proxy(getHandle(), proxy.getHandle());
    }

    /**
     * Returns the proxy widgets for an action.
     * 
     * @return a List of proxy widgets
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public List getProxies() {
        Handle[] proxies = gtk_action_get_proxies(getHandle());
        List objs = new ArrayList();
        for (int i = 0; i < proxies.length; i++) {
            objs.add(Widget.getWidget(proxies[i]));
        }
        return objs;
    }

    /**
     * Installs the accelerator for action if action has an accel path and
     * group. Since multiple proxies may independently trigger the installation
     * of the accelerator, the action counts the number of times this function
     * has been called and doesn't remove the accelerator until
     * {@link Action#disconnectAccelerator()} has been called as many times.
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void connectAccelerator() {
        gtk_action_connect_accelerator(getHandle());
    }

    /**
     * Undoes the effect of one call to {@link Action#connectAccelerator()}.
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void disconnectAccelerator() {
        gtk_action_disconnect_accelerator(getHandle());
    }

    public String getAcceleratorPath() {
        return gtk_action_get_accel_path(getHandle());
    }

    public boolean isSensitive() {
        return gtk_action_is_sensitive(getHandle());
    }

    public void setSensitive(boolean sensitive) {
        gtk_action_set_sensitive(getHandle(), sensitive);
    }

    public boolean isVisible() {
        return gtk_action_is_visible(getHandle());
    }

    public void setVisible(boolean visible) {
        gtk_action_set_visible(getHandle(), visible);
    }

    /**
     * Retrieve the runtime type used by the GLib library.
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public static org.gnu.glib.Type getType() {
        return new org.gnu.glib.Type(gtk_action_get_type());
    }

    /**
     * Sets the accel path for this action. All proxy widgets associated with
     * the action will have this accel path, so that their accelerators are
     * consistent.
     * 
     * @param path
     *            The accelerator path
     * @since 2.8
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void setAccelPath(String path) {
        gtk_action_set_accel_path(this.getHandle(), path);
    }

    /**
     * Sets the {@link org.gnu.gtk.AccelGroup} in which the accelerator for this
     * action will be installed.
     * 
     * @param group
     *            an AccelGroup or null
     * @since 2.8
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void setAccelGroup(AccelGroup group) {
        if (group != null)
            gtk_action_set_accel_group(this.getHandle(), group.getHandle());
        else
            gtk_action_set_accel_group(this.getHandle(), null);
    }

    /**
     * Register an object to receive action activation event notification.
     * 
     * @param listener
     *            The object that has implemented the ActionListener interface
     *            that is to receive the activation events.
     * @since 2.8
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void addListener(ActionListener listener) {
        int i = findListener(this.actionListeners, listener);
        if (i == -1) {
            if (null == this.actionListeners) {
                evtMap.initialize(this, ActionEvent.Type.ACTIVATE);
                this.actionListeners = new Vector();
            }

            this.actionListeners.addElement(listener);
        }
    }

    /**
     * Unregister an object that was receiving focus event notification.
     * 
     * @param listener
     *            The object that is to no longer receive focus events.
     * @since 2.8
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    public void removeListener(ActionListener listener) {
        int i = findListener(this.actionListeners, listener);
        if (i > -1)
            this.actionListeners.remove(i);
        if (0 == this.actionListeners.size()) {
            evtMap.uninitialize(this, ActionEvent.Type.ACTIVATE);
            this.actionListeners = null;
        }
    }

    protected void fireActionEvent(ActionEvent event) {
        if (null == this.actionListeners)
            return;
        int size = this.actionListeners.size();
        int i = 0;
        while (i < size) {
            ActionListener al = (ActionListener) actionListeners.elementAt(i);
            al.actionEvent(event);
            i++;
        }
    }

    protected void handleActivate() {
        fireActionEvent(new ActionEvent(this, ActionEvent.Type.ACTIVATE));
    }

    static {
        evtMap.addEvent("activate", "handleActivate",
                ActionEvent.Type.ACTIVATE, ActionEvent.class);
    }

    /**
     * @since 2.8
     * @param list
     * @param listener
     * @return
     * @deprecated Superceeded by java-gnome 4.0; a method along these lines
     *             may well exist in the new bindings, but if it does it likely
     *             has a different name or signature due to the shift to an
     *             algorithmic mapping of the underlying native libraries.
     */
    protected static int findListener(Vector list, Object listener) {
        if (null == list || null == listener)
            return -1;
        return list.indexOf(listener);
    }

    native static final protected int gtk_action_get_type();

    native static final protected Handle gtk_action_new(String name,
            String label, String tooltip, String stockId);

    native static final protected String gtk_action_get_name(Handle action);

    native static final protected void gtk_action_activate(Handle action);

    native static final protected Handle gtk_action_create_icon(Handle action,
            int iconSize);

    native static final protected Handle gtk_action_create_menu_item(
            Handle action);

    native static final protected Handle gtk_action_create_tool_item(
            Handle action);

    native static final protected void gtk_action_connect_proxy(Handle action,
            Handle proxy);

    native static final protected void gtk_action_disconnect_proxy(
            Handle action, Handle proxy);

    native static final protected Handle[] gtk_action_get_proxies(Handle action);

    native static final protected void gtk_action_connect_accelerator(
            Handle action);

    native static final protected void gtk_action_disconnect_accelerator(
            Handle action);

    native static final protected String gtk_action_get_accel_path(Handle action);

    native static final protected void gtk_action_set_accel_path(Handle action,
            String path);

    native static final protected boolean gtk_action_is_sensitive(Handle action);

    native static final protected boolean gtk_action_get_sensitive(Handle action);

    native static final protected void gtk_action_set_sensitive(Handle action,
            boolean sensitive);

    native static final protected boolean gtk_action_is_visible(Handle action);

    native static final protected boolean gtk_action_get_visible(Handle action);

    native static final protected void gtk_action_set_visible(Handle action,
            boolean visible);

    native static final protected void gtk_action_set_accel_group(
            Handle action, Handle accelGroup);

}
