#import "JubGtkChatUI.h"
-struct show_chat_params {
- GtkWidget *window;
- OFString *title;
-};
-
-static gboolean show_chat(gpointer data)
-{
- struct show_chat_params *params = data;
-
- gtk_window_set_title(GTK_WINDOW(params->window),
- [params->title UTF8String]);
- gtk_widget_show(params->window);
-
- g_object_unref(params->window);
- [params->title release];
- free(params);
-
- return FALSE;
-}
-
struct add_text_params {
OFString *name;
OFString *text;
return FALSE;
}
+struct call_send_block_params {
+ jub_send_block_t block;
+ JubGtkChatUI *chat;
+};
+
static gboolean call_send_block(GtkEntry *entry, GdkEventKey *event,
gpointer data)
{
- if (event->keyval != GDK_KEY_Return) return TRUE;
+ struct call_send_block_params *params = data;
+ if (event->keyval != GDK_KEY_Return &&
+ event->keyval != GDK_KEY_KP_Enter) return TRUE;
- jub_send_block_t block = data;
OFString *text =
[[OFString alloc] initWithUTF8String: gtk_entry_get_text(entry)];
gtk_entry_set_text(entry, "");
- block(text);
+ params->block(text);
+ [params->chat addMessage: text
+ sender: @"You"];
[text release];
return TRUE;
}
-static gboolean add_tags(gpointer data) {
- gtk_text_buffer_create_tag(data, "bold", "weight",
- PANGO_WEIGHT_BOLD, NULL);
+static gboolean call_close_block(GtkWidget *object, gpointer data)
+{
+ jub_close_block_t block = data;
+ block();
+
+ return FALSE;
+}
+
+struct init_params {
+ OFString *title;
+ JubGtkChatUI *object;
+ volatile BOOL *initialized;
+};
+
+static gboolean init(gpointer data)
+{
+ struct init_params *params = data;
+
+ GtkTextView *chat_view;
+ GtkEntry *chat_entry;
+
+ GtkBuilder *builder = gtk_builder_new();
+ gtk_builder_add_from_file(builder, "data/gtk/chat.ui", NULL);
+
+ params->object.chat_window = GTK_WIDGET(
+ gtk_builder_get_object(builder, "ChatWindow"));
+ g_signal_connect(params->object.chat_window, "destroy",
+ G_CALLBACK(call_close_block), params->object.closeBlock);
+
+
+ chat_view = GTK_TEXT_VIEW(
+ gtk_builder_get_object(builder, "ChatTextView"));
+ params->object.chat_buffer = gtk_text_view_get_buffer(chat_view);
+ gtk_text_buffer_create_tag(params->object.chat_buffer, "bold",
+ "weight", PANGO_WEIGHT_BOLD, NULL);
+
+ chat_entry = GTK_ENTRY(
+ gtk_builder_get_object(builder, "ChatEntry"));
+ struct call_send_block_params *send_params =
+ [params->object allocMemoryWithSize: sizeof(*send_params)];
+ send_params->block = params->object.sendBlock;
+ send_params->chat = params->object;
+ g_signal_connect(chat_entry, "key_release_event",
+ G_CALLBACK(call_send_block), send_params);
+
+ gtk_window_set_title(GTK_WINDOW(params->object.chat_window),
+ [params->title UTF8String]);
+ gtk_widget_show(params->object.chat_window);
+
+ *params->initialized = YES;
+
+ g_object_unref(builder);
+ [params->title release];
+ free(params);
return FALSE;
}
@implementation JubGtkChatUI
+@synthesize chat_window;
+@synthesize chat_buffer;
+@synthesize sendBlock;
+@synthesize closeBlock;
+
- initWithTitle: (OFString*)title
+ closeBlock: (jub_close_block_t)closeBlock_
sendBlock: (jub_send_block_t)sendBlock_
{
+ volatile BOOL initialized = NO;
self = [super init];
@try {
- GtkTextView *chat_view;
- GtkEntry *chat_entry;
- GtkBuilder *builder = gtk_builder_new();
+ closeBlock = [closeBlock_ copy];
sendBlock = [sendBlock_ copy];
bufferEmpty = YES;
- gtk_builder_add_from_file(builder, "data/gtk/chat.ui", NULL);
-
- chat_window = GTK_WIDGET(
- gtk_builder_get_object(builder, "ChatWindow"));
-
- chat_view = GTK_TEXT_VIEW(
- gtk_builder_get_object(builder, "ChatTextView"));
-
- chat_entry = GTK_ENTRY(
- gtk_builder_get_object(builder, "ChatEntry"));
-
- g_signal_connect(chat_entry, "key_release_event",
- G_CALLBACK(call_send_block), sendBlock);
-
- chat_buffer = gtk_text_view_get_buffer(chat_view);
- g_idle_add(add_tags, chat_buffer);
-
- struct show_chat_params *params = malloc(sizeof(*params));
- params->window = g_object_ref(chat_window);
+ struct init_params *params = malloc(sizeof(*params));
+ params->initialized = &initialized;
params->title = [title retain];
- g_idle_add(show_chat, params);
-
- g_object_unref(builder);
+ params->object = self;
+ g_idle_add(init, params);
} @catch (id e) {
[self release];
@throw e;
}
+ while (!initialized);
+
return self;
}
{
gtk_widget_destroy(chat_window);
[sendBlock release];
+ [closeBlock release];
[super dealloc];
}
- (void)connection: (XMPPConnection*)connection
didReceiveMessage: (XMPPMessage*)message
{
- JubGtkChatUI *chat = [chatMap objectForKey: [message.from bareJID]];
+ JubGtkChatUI *chat =
+ [chatMap objectForKey: [message.from bareJID]];
if (chat == nil) {
OFString * title = [@"Chat with " stringByAppendingString:
[message.from bareJID]];
- chat = [JubGtkChatUI alloc];
- [[chat initWithTitle: title
- sendBlock: ^(OFString *text) {
- XMPPMessage *msg =
- [XMPPMessage messageWithType: @"chat"];
- msg.to = message.from;
- msg.body = text;
- [connection sendStanza: msg];
-
- [chat addMessage: msg.body
- sender: [message.to bareJID]];
- }] autorelease];
+
+ chat = [[[JubGtkChatUI alloc]
+ initWithTitle: title
+ closeBlock: ^{
+ [chatMap removeObjectForKey:
+ [message.from bareJID]];
+ }
+ sendBlock: ^(OFString *text) {
+ XMPPMessage *msg =
+ [XMPPMessage messageWithType: @"chat"];
+ msg.to = message.from;
+ msg.body = text;
+ [connection sendStanza: msg];
+ }
+ ] autorelease];
[chatMap setObject: chat
forKey: [message.from bareJID]];
}
+
[chat addMessage: message.body
sender: [message.from bareJID]];
}