/*
 * GToolKit - Objective-C interface to the GIMP Toolkit
 * Copyright (c) 1998  Elmar Ludwig - Universitaet Osnabrueck
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include <stdarg.h>
#include <Foundation/NSAutoreleasePool.h>
#include <GToolKit/GToolKit.h>

static void clicked (GtkWidget *widget, int *data)
{
    *data = [Gtk_to_Object(widget, 0) tag];
    [GTKApp mainQuit];
}

static void delete (GtkWidget *widget, GdkEvent *event, int *data)
{
    clicked(widget, data);
}

static GTKButton *insert (GTKBox *box, NSString *label, gpointer data, int tag)
{
    GTKButton *button = [GTKButton buttonWithLabel:label];
    GtkButton *gtk_button = [button gtk];

    [button setTag:tag];
    [box packStart:button expand:YES fill:NO padding:0];
    gtk_misc_set_padding((GtkMisc *) gtk_button->child, 4, 0);
    GTK_WIDGET_SET_FLAGS(gtk_button, GTK_CAN_DEFAULT);
    gtk_signal_connect((GtkObject *) gtk_button, "clicked",
		       (GtkSignalFunc) clicked, data);
    return button;
}

/*
 * Display a modal message box or alert panel.
 * Return value is n-1 if button number n is clicked (e.g. 0 for button1).
 */
int GTKRunMessageBox (NSString *title, NSString *format, NSString *button1,
		      NSString *button2, NSString *button3, ...)
{
    GTKDialog *window = [GTKDialog dialog];
    GTKBox *hbox = (GTKBox *) [window actionArea];
    GTKBox *vbox = (GTKBox *) [window vbox];
    GTKButton *focus = nil;
    GTKLabel *label;
    NSString *text;
    int result, tag = 0;
    va_list ap;

    if (button1) focus = insert(hbox, button1, &result, tag);
    if (button2) insert(hbox, button2, &result, ++tag);
    if (button3) insert(hbox, button3, &result, ++tag);
    if (focus) [window setDefault:focus], [window setFocus:focus];
    if (title) [window setTitle:title];

    va_start(ap, button3);
    text = [[NSString alloc] initWithFormat:format arguments:ap];
    label = [GTKLabel labelWithStr:text];
    [text release];
    va_end(ap);

    [label setPadding:10 ypad:10];
    [label setJustify:GTK_JUSTIFY_LEFT];
    [vbox packStartDefaults:label];
    [window setTag:tag];
    [window show];

    gtk_signal_connect([window gtk], "delete_event", (GtkSignalFunc) delete,
		       &result);
    [GTKApp grabAdd:window];
    [GTKApp main];		// start modal loop
    [GTKApp grabRemove:window];
    [window destroy];
    return result;
}

@implementation GTKApplication

GTKApplication *GTKApp;		// the application object

 - init
{
    g_error("[GTKApplication init]: need argc and argv");
    return nil;
}

/*
 * Initialize a new GTKApplication object and store it in the global
 * variable GTKApp. Note that you cannot create more than one application
 * object in your program. This method will modify the program's command
 * line arguments as given by /argc/ and /argv/ and remove any options
 * related to GTK (such as |--display| or |--class|) from the argument list.
 */
- initWithArgc:(int *) argc argv:(char ***) argv
{
    if (GTKApp == nil)
	GTKApp = [super init], gtk_init(argc, argv);
    return GTKApp;
}

/*
 * Set the application object's delegate or unset it (if /delegate/ is |nil|).
 */
- (void) setDelegate:_delegate
{
    delegate = _delegate;
}

/*
 * Return the application object's delegate.
 */
- delegate
{
    return delegate;
}

/*
 * Start the application's main event loop.
 */
- (void) run
{
    [self main];
}

/*
 * Tell the application's main event loop to finish. This will cause the
 * @-run method to return, which will normally end the program.
 * The /sender/ parameter is ignored.<p>
 * If the delegate implements the method:
 * <pre>
 * - (BOOL) applicationShouldTerminate:(GTKApplication *) sender</pre>
 *
 * this message is sent to the delegate to determine whether the application
 * should actually terminate.
 */
- (void) terminate:sender
{
    if ([delegate respondsToSelector:@selector(applicationShouldTerminate:)] &&
	[delegate applicationShouldTerminate:self] == NO) return;

    if ([self mainLevel] == 1) [self mainQuit];
    else [self exit:0];
}
@end
