#include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSNotification.h>

%extern
@class GTKWindow;

/*
 * Notification strings
 */
extern NSString *GTKWindowDidBecomeMainNotification;
extern NSString *GTKWindowDidResignMainNotification;
extern NSString *GTKWindowWillCloseNotification;
extern NSString *GTKWindowWillOpenNotification;

/*
 * These methods may be implemented by the delegate.
 */
@protocol GTKWindowDelegate
- (void) windowDidBecomeMain:(NSNotification *) event;
- (void) windowDidResignMain:(NSNotification *) event;
- (BOOL) windowShouldClose:(GTKWindow *) sender;
- (void) windowWillClose:(NSNotification *) event;
@end

%end
%interface
{
    id delegate;		// delegate of this window object
@private
    guint handler_id;		// /delete_event/ signal handler id
}

%end

NSString *GTKWindowDidBecomeMainNotification = @"GTKWindowDidBecomeMain";
NSString *GTKWindowDidResignMainNotification = @"GTKWindowDidResignMain";
NSString *GTKWindowWillCloseNotification = @"GTKWindowWillClose";
NSString *GTKWindowWillOpenNotification = @"GTKWindowWillOpen";

static gint focus_in_window (GtkWidget *win, GdkEvent *event, GTKWindow *self)
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    [[NSNotificationCenter defaultCenter] postNotificationName:
	GTKWindowDidBecomeMainNotification object:self];
    [pool release];
    return NO;
}

static gint focus_out_window (GtkWidget *win, GdkEvent *event, GTKWindow *self)
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    [[NSNotificationCenter defaultCenter] postNotificationName:
	GTKWindowDidResignMainNotification object:self];
    [pool release];
    return NO;
}

static gint delete_window (GtkWidget *win, GdkEvent *event, GTKWindow *self)
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    id delegate = [self delegate];
    gint result = NO;

    if ([delegate respondsToSelector:@selector(windowShouldClose:)] &&
	[delegate windowShouldClose:self] == NO) result = YES;
    [pool release];
    return result;
}

static void destroy_window (GtkWidget *win, GTKWindow *self)
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    [[NSNotificationCenter defaultCenter] postNotificationName:
	GTKWindowWillCloseNotification object:self];
    [pool release];
}

 - (id) initWithGtk:(gpointer) _gtk
{
    [super initWithGtk:_gtk];

    gtk_signal_connect(_gtk, "focus_in_event",
			(GtkSignalFunc) focus_in_window, self);
    gtk_signal_connect(_gtk, "focus_out_event",
			(GtkSignalFunc) focus_out_window, self);
    gtk_signal_connect(_gtk, "destroy", (GtkSignalFunc) destroy_window, self);

    [[NSNotificationCenter defaultCenter] postNotificationName:
	GTKWindowWillOpenNotification object:self];

    [self ref];		// first reference is missing (due to floating flag)
    return  self;	// avoid bug in objcdoc
}

/*
 * Set the delegate object of this window or unset it (if /delegate/
 * is |nil|). If the delegate implements some of the methods described
 * in the protocol @proto(GTKWindowDelegate), it will be notified by
 * the window on the corresponding events.
 */
- (void) setDelegate:(id) object
{
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

    if (delegate) [center removeObserver:delegate name:nil object:self];
    delegate = object;

    if ([object respondsToSelector:@selector(windowDidBecomeMain:)])
	[center addObserver:object selector:@selector(windowDidBecomeMain:)
		name:GTKWindowDidBecomeMainNotification object:self];
    if ([object respondsToSelector:@selector(windowDidResignMain:)])
	[center addObserver:object selector:@selector(windowDidResignMain:)
		name:GTKWindowDidResignMainNotification object:self];
    if ([object respondsToSelector:@selector(windowWillClose:)])
	[center addObserver:object selector:@selector(windowWillClose:)
		name:GTKWindowWillCloseNotification object:self];

    if (handler_id == 0 &&
	[object respondsToSelector:@selector(windowShouldClose:)])
	handler_id = gtk_signal_connect(gtk, "delete_event",
					(GtkSignalFunc) delete_window, self);
}

/*
 * Return this window's delegate object.
 */
- (id) delegate
{
    return delegate;
}

/*
 * Send a /delete_event/ signal to this window, i.e. act as if the user
 * had closed the receiver via the window manager. The /sender/ parameter
 * is ignored.<p>
 * If the delegate implements the method:
 * <pre>
 * - (BOOL) windowShouldClose:(GTKWindow *) sender</pre>
 *
 * this message is sent to the delegate to determine whether the window
 * should actually be closed. If it returns |YES|, this method will post
 * the GTKWindowWillCloseNotification to the default notification center
 * and close the window.
 * @see -destroy
 */
- (void) performClose:(id) sender
{
    GdkEvent event = { GDK_DELETE };
    gint result;

    event.any.window = ((GtkWidget *) gtk)->window;
    gtk_signal_emit_by_name(gtk, "delete_event", &event, &result);
}

#define gtk	((GtkWindow *) gtk)
- (NSString *) title
{
    return gtoolkit_objc_string(gtk->title);
}
- (GTKWidget *) focusWidget
{
    return GTOOLKIT_OBJECT(gtk->focus_widget);
}
- (GTKWidget *) defaultWidget
{
    return GTOOLKIT_OBJECT(gtk->default_widget);
}
#undef gtk
