/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2003 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 org.gnu.gdk.Event;
import org.gnu.gdk.EventKey;
import org.gnu.glib.Handle;

/**
 * This class is a catch-all for methods in GTK that are not associated with a
 * GTK object.
 *
 * @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.Gtk</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 Gtk {
    /**
     * Helper method for init and initCheck. Set a default application name to
     * be passed to GTK native init function.
     * @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 String[] initArgs(String[] args) {
        String appName = System.getProperty("gnome.appName", "java-gnome");

        if (args == null) {
            args = new String[] { appName };
        } else {
            String[] newArr = new String[args.length + 1];
            System.arraycopy(args, 0, newArr, 1, args.length);
            newArr[0] = appName;
            args = newArr;
        }
        return args;
    }

    /**
     * This method should be called before using any java-gnome objects. It
     * initialized everything needed to use the native libraries. This method
     * will terminate you program if it is unable to initialize the native
     * libraries.
     * 
     * @param args
     *            The command line arguments passed to the application.
     * @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 void init(String[] args) {
        int[] argLen = new int[1];

        args = initArgs(args);
        argLen[0] = args.length;

        Gtk.gtk_init(argLen, args);
    }

    /**
     * This method does the same work as {@link #init} with only a single
     * change: It does not terminate the program if the GUI can't be
     * initialized. Instead it throws a {@link GtkInitException}.
     * 
     * @param args
     *            The command line arguments passed to the application.
     * @throws GtkInitException
     * @since 2.8.2
     * @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 void initCheck(String[] args) throws GtkInitException {
        int[] argLen = new int[1];

        args = initArgs(args);
        argLen[0] = args.length;

        if (!Gtk.gtk_init_check(argLen, args))
            throw new GtkInitException();
    }

    /**
     * Runs the main event loop.
     * @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 void main() {
        gtkThread = Thread.currentThread();
        Gtk.gtk_main();
    }

    private static Thread gtkThread;

    /**
     * Returns true if the current thread is the Gtk thread
     * @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 boolean isGtkThread() {
        return gtkThread == Thread.currentThread();
    }

    /**
     * Runs a single iteration of the main loop. If no events are waiting to be
     * processed GTK will block until the next event is noticed.
     * @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 boolean mainIteration() {
        return Gtk.gtk_main_iteration();
    }

    /**
     * Quit the main event loop.
     * @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 void mainQuit() {
        Gtk.gtk_main_quit();
    }

    /**
     * Checks if any events are pending. This can be used to update the GUI and
     * invoke timeouts etc. while doing some time intensive computation.
     * 
     * @return true if any events are pending.
     * @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 boolean eventsPending() {
        return Gtk.gtk_events_pending();
    }

    static String getTypeName(Handle handle) {
        try {
            return gtk_type_name(handle);
        } catch (Throwable t) {
            System.err.println(t.toString());
            return null;
        }
    }

    /**
     * All this function does is to return TRUE. This can be useful for example
     * if you want to inhibit the deletion of a window. Of course you should not
     * do this as the user expects a reaction from clicking the close icon of
     * the window.
     * @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 boolean getTrue() {
        return gtk_true();
    }

    /**
     * Analogical to {@link #getTrue}. This function does nothing but always
     * return FALSE.
     * @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 boolean getFalse() {
        return gtk_false();
    }

    /**
     * Runs a single iteration of the mainloop. If no events are available
     * either return or block dependent on the value of <tt>blocking</tt>.
     * 
     * @param blocking
     *            TRUE if you want GTK+ to block if no events are pending.
     * @return TRUE if {@link #mainQuit} has been called for the innermost
     *         mainloop.
     * @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 boolean mainIterationDo(boolean blocking) {
        return gtk_main_iteration_do(blocking);
    }

    // Private data members for keysnooping data.
    private static KeySnoopMethod keySnooperMethod = null;

    private static int keySnooperId = 0;

    /**
     * Installs a key snooper method, which will get called on all key events
     * before delivering them normally. This can be used to implement custom key
     * event handling.
     * @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 void setKeySnoopMethod(KeySnoopMethod method) {
        keySnooperId = gtk_key_snooper_install(method, "handleKeySnoopEvent");
        keySnooperMethod = method;
    }

    /**
     * Removes current the key snooper method.
     * @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 void removeKeySnoopMethod() {
        gtk_key_snooper_remove(keySnooperId);
        keySnooperMethod = null;
        keySnooperId = 0;
    }

    protected static boolean handleKeySnoopEvent(Handle widget, Handle event) {
        if (keySnooperMethod != null) {
            Widget widg = Widget.getWidget(widget);
            EventKey evt = EventKey.getEventKey(event);
            return keySnooperMethod.keyEvent(widg, evt);
        } else {
            return false;
        }
    }

    /**
     * Sends an event to a widget, propagating the event to parent widgets if
     * the event remains unhandled.
     * 
     * <b>NOTE</b>: You most likely don't want to use this function.
     * Synthesizing events is rarely needed. Consider asking on the mailing list
     * for better ways to achieve your goals.
     * 
     * @param widget
     *            A Widget.
     * @param event
     *            An Event.
     * @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 propagateEvent(Widget widget, Event event) {
        gtk_propagate_event(widget.getHandle(), event.getHandle());
    }

    // Load the library
    static {
        System.loadLibrary(org.gnu.gtk.Config.LIBRARY_NAME
                + org.gnu.gtk.Config.GTK_API_VERSION);
    }

    native static final protected void gtk_init(int[] argc, String[] args);

    native static final protected boolean gtk_init_check(int[] argc,
            String[] args);

    native static final protected void gtk_disable_setlocale();

    native static final protected String gtk_set_locale();

    native static final protected Handle gtk_get_default_language();

    native static final protected boolean gtk_events_pending();

    native static final protected void gtk_main_do_event(Handle event);

    native static final protected void gtk_main();

    native static final protected int gtk_main_level();

    native static final protected void gtk_main_quit();

    native static final protected boolean gtk_main_iteration();

    native static final protected void gtk_grab_add(Handle widget);

    native static final protected Handle gtk_grab_get_current();

    native static final protected void gtk_grab_remove(Handle widget);

    native static final protected Handle gtk_get_current_event();

    native static final protected int gtk_get_current_event_time();

    native static final protected Handle gtk_get_event_widget(Handle event);

    native static final protected String gtk_type_name(Handle type);

    native static final private boolean gtk_true();

    native static final private boolean gtk_false();

    native static final private boolean gtk_main_iteration_do(boolean blocking);

    native static final private int gtk_key_snooper_install(
            KeySnoopMethod snooper, String callback);

    native static final private void gtk_key_snooper_remove(
            int snooper_handler_id);

    native static final private void gtk_propagate_event(Handle widget,
            Handle event);

    /*
     * Undocumented functions. native static final private String
     * gtk_check_version(int required_major, int required_minor, int
     * required_micro);
     * @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.
     */
    /*
     * Deprecated functions. native static final private void gtk_exit(int
     * error_code); native static final private int gtk_timeout_add(int
     * interval, int function, gpointer data); native static final private int
     * gtk_timeout_add_full(int interval, int function, int marshal, gpointer
     * data, int destroy); native static final private void
     * gtk_timeout_remove(int timeout_handler_id); native static final private
     * int gtk_idle_add(int function, gpointer data); native static final
     * private int gtk_idle_add_priority(int priority, int function, gpointer
     * data); native static final private int gtk_idle_add_full(int priority,
     * int function, int marshal, gpointer data, int destroy); native static
     * final private void gtk_idle_remove(int idle_handler_id); native static
     * final private void gtk_idle_remove_by_data(gpointer data); native static
     * final private int gtk_input_add_full(int source, int condition, int
     * function, int marshal, gpointer data, int destroy); native static final
     * private void gtk_input_remove(int input_handler_id);
     * @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 Gtk() {
        // prevent instantiation
    }
}
