/*
 * 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.Vector;

import org.gnu.glib.EventMap;
import org.gnu.glib.EventType;
import org.gnu.gtk.event.ButtonEvent;
import org.gnu.gtk.event.ButtonListener;
import org.gnu.glib.Handle;

/**
 * A widget that creates a signal when clicked on. This is generally used to
 * attach a function to that is called when the button is pressed.
 * <p>
 * The gtk.Button widget can hold any valid child widget. That is it can hold
 * most any other standard gtk.Widget. The most commonly used child is the
 * gtk.Label.
 *
 * @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.Button</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 Button extends Bin {

    /**
     * Creates a new Button 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 Button() {
        super(gtk_button_new());
    }

    /**
     * Creates a button widget with a gtk.Label child containing the given text.
     * <p>
     * If <code>hasMnemonic</code> is true, the label will be interpreted as
     * containing <i>Mnemonic</i> characters (keyboard accelerators). If
     * characters in label are proceeded by an underscore character, they will
     * be underlined. The first underlined character will be taken as the
     * mnemonic - pressing <code>Alt</code> and that character will activate
     * the button.
     * 
     * @param label
     *            Text to appear on the button
     * @param hasMnemonic
     *            See above description
     * @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 Button(String label, boolean hasMnemonic) {
        super(init(label, hasMnemonic));
    }

    private static Handle init(String label, boolean hasMnemonic) {
        if (hasMnemonic)
            return gtk_button_new_with_mnemonic(label);
        else
            return gtk_button_new_with_label(label);
    }

    /**
     * Constructs a button using a stock item. Stock items are standard icons
     * and text strings. The use of these is highly encouraged as they allow gtk
     * themes to have greater control over applications and so give a more
     * consistent interface to the user. <br>
     * Example:
     * <code>Button myButton = new Button( new StockItem( StockItem.NO );
     * )</code>
     * 
     * @param stockItem
     *            A gtk stock item
     * @see GtkStockItem
     * @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 Button(GtkStockItem stockItem) {
        super(gtk_button_new_from_stock(stockItem.getString()));
    }

    /**
     * Constructs a button using a String that represents a stock item. Stock
     * items are standard icons and text strings. The use of these is highly
     * encouraged as they allow gtk themes to have greater control over
     * applications and so give a more consistent interface to the user. <br>
     * Example: <code>Button myButton = new Button( StockItem.NO;
     * )</code>
     * 
     * @param stockItem
     *            A String representing a stock item
     * @see GtkStockItem
     * @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 Button(String stockItem) {
        super(gtk_button_new_from_stock(stockItem));
    }

    /**
     * Construct a button using a handle to a native resource.
     * @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 Button(Handle handle) {
        super(handle);
    }

    /**
     * Construct a button using a handle to a native resource.
     * @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 Button getButton(Handle handle) {
        if (handle == null)
            return null;

        Button obj = (Button) getGObjectFromHandle(handle);
        if (obj == null)
            obj = new Button(handle);

        return obj;
    }

    /**
     * Sends a <i>pressed</i> signal to the button. If handlers have been set
     * up for this event then they will be called
     * @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 press() {
        gtk_button_pressed(getHandle());
    }

    /**
     * Sends a <i>released</i> signal to the button. If handlers have been set
     * up for this event, they will be called.
     * @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 release() {
        gtk_button_released(getHandle());
    }

    /**
     * Sends a <i>clicked</i> signal to the button. If handlers have been set
     * up for this event, they will be called
     * @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 click() {
        gtk_button_clicked(getHandle());
    }

    /**
     * Sends an <i>enter</i> signal to the button. If handlers have been set up
     * for this event, they will be called.
     * @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 enter() {
        gtk_button_enter(getHandle());
    }

    /**
     * Sends a <i>leave</i> signal to the button. If handlers have been set up
     * for this event, they will be called.
     * @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 leave() {
        gtk_button_leave(getHandle());
    }

    /**
     * Sets the relief style of the edges of the Button 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 setRelief(ReliefStyle newRelief) {
        gtk_button_set_relief(getHandle(), newRelief.getValue());
    }

    /**
     * Returns the current relief style of the button
     * @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 ReliefStyle getRelief() {
        return ReliefStyle.intern(gtk_button_get_relief(getHandle()));
    }

    /**
     * Sets the text of the label of the button to newLabel. If setUseStock has
     * been called or this object was created using stock buttons, then newLabel
     * should be the name of the stock item to be used.
     * @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 setLabel(String newLabel) {
        gtk_button_set_label(getHandle(), newLabel);
    }

    /**
     * Returns the label which is being used on the button.
     * @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 getLabel() {
        return gtk_button_get_label(getHandle());
    }

    /**
     * If true, an underline in the text of the button label indicates the next
     * character should be used for the mnemonic accelerator key.
     * @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 setUseUnderline(boolean useUnderLine) {
        gtk_button_set_use_underline(getHandle(), useUnderLine);
    }

    /**
     * Returns whether an embedded underline in the button label indicates a
     * mnemonic.
     * @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 boolean getUseUnderline() {
        return gtk_button_get_use_underline(getHandle());
    }

    // TODO: give a doc link to list of stock items.
    /**
     * Setting this will true will make the widget try to interpret the label as
     * a stock item. If the stock id is unknown, it will be treated as a normal
     * label.
     * <p>
     * Stock items are standard icons and strings. These are included in Gtk
     * themes, so that the appearance of all applications follows their theme.
     * The use of stock items is highly recommended.
     * 
     * @param useStock
     *            true if this button should use stock items
     * @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 setUseStock(boolean useStock) {
        gtk_button_set_use_stock(getHandle(), useStock);
    }

    /**
     * Returns true if this button is using stock items
     * @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 boolean getUseStock() {
        return gtk_button_get_use_stock(getHandle());
    }

    public void setFocusOnClick(boolean focusOnClick) {
        gtk_button_set_focus_on_click(getHandle(), focusOnClick);
    }

    public boolean getFocusOnClick() {
        return gtk_button_get_focus_on_click(getHandle());
    }

    public void setAlignment(double xalign, double yalign) {
        gtk_button_set_alignment(getHandle(), xalign, yalign);
    }

    public double getXAlignment() {
        double[] xalign = new double[1];
        double[] yalign = new double[1];
        gtk_button_get_alignment(getHandle(), xalign, yalign);
        return xalign[0];
    }

    public double getYAlignment() {
        double[] xalign = new double[1];
        double[] yalign = new double[1];
        gtk_button_get_alignment(getHandle(), xalign, yalign);
        return yalign[0];
    }

    public void setImage(Widget image) {
        gtk_button_set_image(getHandle(), image.getHandle());
    }

    public Widget getImage() {
        return Widget.getWidget(gtk_button_get_image(getHandle()));
    }

    /***************************************************************************
     * EVENT LISTENERS
     **************************************************************************/

    /**
     * Listeners for handling button events
     * @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.
     */
    private Vector buttonListeners = null;

    /**
     * Register an object to handle button events.
     * 
     * @see org.gnu.gtk.event.ButtonListener
     * @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(ButtonListener listener) {
        // Don't add the listener a second time if it is in the Vector.
        int i = findListener(buttonListeners, listener);
        if (i == -1) {
            if (null == buttonListeners) {
                evtMap.initialize(this, ButtonEvent.Type.ACTIVATE);
                evtMap.initialize(this, ButtonEvent.Type.CLICK);
                evtMap.initialize(this, ButtonEvent.Type.ENTER);
                evtMap.initialize(this, ButtonEvent.Type.LEAVE);
                evtMap.initialize(this, ButtonEvent.Type.PRESS);
                evtMap.initialize(this, ButtonEvent.Type.RELEASE);
                buttonListeners = new Vector();
            }
            buttonListeners.addElement(listener);
        }
    }

    /**
     * Removes a listener
     * 
     * @see #addListener(ButtonListener)
     * @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(ButtonListener listener) {
        int i = findListener(buttonListeners, listener);
        if (i > -1) {
            buttonListeners.remove(i);
        }
        if (0 == buttonListeners.size()) {
            evtMap.uninitialize(this, ButtonEvent.Type.ACTIVATE);
            evtMap.uninitialize(this, ButtonEvent.Type.CLICK);
            evtMap.uninitialize(this, ButtonEvent.Type.ENTER);
            evtMap.uninitialize(this, ButtonEvent.Type.LEAVE);
            evtMap.uninitialize(this, ButtonEvent.Type.PRESS);
            evtMap.uninitialize(this, ButtonEvent.Type.RELEASE);
            buttonListeners = null;
        }
    }

    protected void fireButtonEvent(ButtonEvent event) {
        if (null == buttonListeners) {
            return;
        }
        int size = buttonListeners.size();
        int i = 0;
        while (i < size) {
            ButtonListener bl = (ButtonListener) buttonListeners.elementAt(i);
            bl.buttonEvent(event);
            i++;
        }
    }

    private void handleActivate() {
        fireButtonEvent(new ButtonEvent(this, ButtonEvent.Type.ACTIVATE));
    }

    private void handleClick() {
        fireButtonEvent(new ButtonEvent(this, ButtonEvent.Type.CLICK));
    }

    private void handleEnter() {
        fireButtonEvent(new ButtonEvent(this, ButtonEvent.Type.ENTER));
    }

    private void handleLeave() {
        fireButtonEvent(new ButtonEvent(this, ButtonEvent.Type.LEAVE));
    }

    private void handlePress() {
        fireButtonEvent(new ButtonEvent(this, ButtonEvent.Type.PRESS));
    }

    private void handleRelease() {
        fireButtonEvent(new ButtonEvent(this, ButtonEvent.Type.RELEASE));
    }

    public Class getEventListenerClass(String signal) {
        Class cls = evtMap.getEventListenerClass(signal);
        if (cls == null)
            cls = super.getEventListenerClass(signal);
        return cls;
    }

    public EventType getEventType(String signal) {
        EventType et = evtMap.getEventType(signal);
        if (et == null)
            et = super.getEventType(signal);
        return et;
    }

    private static EventMap evtMap = new EventMap();
    static {
        addEvents(evtMap);
    }

    /**
     * Implementation method to build an EventMap for this widget class. Not
     * useful (or supported) for application use.
     * @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.
     */
    private static void addEvents(EventMap anEvtMap) {
        anEvtMap.addEvent("activate", "handleActivate",
                ButtonEvent.Type.ACTIVATE, ButtonListener.class);
        anEvtMap.addEvent("clicked", "handleClick", ButtonEvent.Type.CLICK,
                ButtonListener.class);
        anEvtMap.addEvent("enter", "handleEnter", ButtonEvent.Type.ENTER,
                ButtonListener.class);
        anEvtMap.addEvent("leave", "handleLeave", ButtonEvent.Type.LEAVE,
                ButtonListener.class);
        anEvtMap.addEvent("pressed", "handlePress", ButtonEvent.Type.PRESS,
                ButtonListener.class);
        anEvtMap.addEvent("released", "handleRelease",
                ButtonEvent.Type.RELEASE, ButtonListener.class);
    }

    /**
     * Retrieve the runtime type used by the GLib library.
     * @deprecated Superceeded by java-gnome 4.0.
     */
    public static org.gnu.glib.Type getType() {
        return new org.gnu.glib.Type(gtk_button_get_type());
    }

    native static final protected int gtk_button_get_type();

    native static final protected Handle gtk_button_new();

    native static final protected Handle gtk_button_new_with_label(String label);

    native static final protected Handle gtk_button_new_from_stock(
            String stock_id);

    native static final protected Handle gtk_button_new_with_mnemonic(
            String label);

    native static final protected void gtk_button_pressed(Handle button);

    native static final protected void gtk_button_released(Handle button);

    native static final protected void gtk_button_clicked(Handle button);

    native static final protected void gtk_button_enter(Handle button);

    native static final protected void gtk_button_leave(Handle button);

    native static final protected void gtk_button_set_relief(Handle button,
            int relief);

    native static final protected int gtk_button_get_relief(Handle button);

    native static final protected void gtk_button_set_label(Handle button,
            String label);

    native static final protected String gtk_button_get_label(Handle button);

    native static final protected void gtk_button_set_use_underline(
            Handle button, boolean useUnderline);

    native static final protected boolean gtk_button_get_use_underline(
            Handle button);

    native static final protected void gtk_button_set_use_stock(Handle button,
            boolean useStock);

    native static final protected boolean gtk_button_get_use_stock(Handle button);

    native static final protected void gtk_button_set_focus_on_click(
            Handle button, boolean focus);

    native static final protected boolean gtk_button_get_focus_on_click(
            Handle button);

    native static final protected void gtk_button_set_alignment(Handle button,
            double xalign, double yalign);

    native static final protected void gtk_button_get_alignment(Handle button,
            double[] xalign, double[] yalign);

    native static final protected void gtk_button_set_image(Handle button,
            Handle image);

    native static final protected Handle gtk_button_get_image(Handle button);

}
