]> cgit.babelmonkeys.de Git - jubjub.git/blob - src/gui/gtk/JubGtkChatUI.m
4a45bcf447016ec5dd48d12f5510d37a56200fb0
[jubjub.git] / src / gui / gtk / JubGtkChatUI.m
1 #import "JubGtkChatUI.h"
2 #import "JubGtkHelper.h"
3
4 struct call_send_block_params {
5         jub_send_block_t block;
6         JubGtkChatUI *chat;
7 };
8
9 static gboolean call_send_block(GtkEntry *entry, GdkEventKey *event,
10     gpointer data)
11 {
12         struct call_send_block_params *params = data;
13         if (event->keyval != GDK_KEY_Return &&
14             event->keyval != GDK_KEY_KP_Enter) return TRUE;
15
16         OFString *text =
17             [[OFString alloc] initWithUTF8String: gtk_entry_get_text(entry)];
18         gtk_entry_set_text(entry, "");
19         params->block(text);
20         [params->chat addMessage: text
21                           sender: @"You"];
22         [text release];
23
24         return TRUE;
25 }
26
27 static gboolean call_close_block(GtkWidget *object, gpointer data)
28 {
29         jub_close_block_t block = data;
30         block();
31
32         return FALSE;
33 }
34
35 struct init_params {
36         OFString *title;
37         JubGtkChatUI *object;
38         volatile BOOL *initialized;
39 };
40
41 static gboolean init(gpointer data)
42 {
43         struct init_params *params = data;
44
45         GtkTextView *chat_view;
46         GtkEntry *chat_entry;
47
48         GtkBuilder *builder = gtk_builder_new();
49         gtk_builder_add_from_file(builder, "data/gtk/chat.ui", NULL);
50
51         params->object.chat_window = GTK_WIDGET(
52             gtk_builder_get_object(builder, "ChatWindow"));
53         g_signal_connect(params->object.chat_window, "destroy",
54             G_CALLBACK(call_close_block), params->object.closeBlock);
55
56
57         chat_view = GTK_TEXT_VIEW(
58             gtk_builder_get_object(builder, "ChatTextView"));
59         params->object.chat_buffer = gtk_text_view_get_buffer(chat_view);
60         gtk_text_buffer_create_tag(params->object.chat_buffer, "bold",
61             "weight", PANGO_WEIGHT_BOLD, NULL);
62
63         chat_entry = GTK_ENTRY(
64             gtk_builder_get_object(builder, "ChatEntry"));
65         struct call_send_block_params *send_params =
66             [params->object allocMemoryWithSize: sizeof(*send_params)];
67         send_params->block = params->object.sendBlock;
68         send_params->chat = params->object;
69         g_signal_connect(chat_entry, "key_release_event",
70             G_CALLBACK(call_send_block), send_params);
71
72         gtk_window_set_title(GTK_WINDOW(params->object.chat_window),
73             [params->title UTF8String]);
74         gtk_widget_show(params->object.chat_window);
75
76         *params->initialized = YES;
77
78         g_object_unref(builder);
79         [params->title release];
80         free(params);
81
82         return FALSE;
83 }
84
85 @implementation JubGtkChatUI
86 @synthesize chat_window;
87 @synthesize chat_buffer;
88 @synthesize sendBlock;
89 @synthesize closeBlock;
90
91 - initWithTitle: (OFString*)title
92      closeBlock: (jub_close_block_t)closeBlock_
93       sendBlock: (jub_send_block_t)sendBlock_
94 {
95         volatile BOOL initialized = NO;
96         self = [super init];
97
98         @try {
99                 closeBlock = [closeBlock_ copy];
100                 sendBlock = [sendBlock_ copy];
101                 bufferEmpty = YES;
102
103                 struct init_params *params = malloc(sizeof(*params));
104                 params->initialized = &initialized;
105                 params->title = [title retain];
106                 params->object = self;
107                 g_idle_add(init, params);
108         } @catch (id e) {
109                 [self release];
110                 @throw e;
111         }
112
113         while (!initialized);
114
115         return self;
116 }
117
118 - (void)dealloc
119 {
120         gtk_widget_destroy(chat_window);
121         [sendBlock release];
122         [closeBlock release];
123
124         [super dealloc];
125 }
126
127 - (void)addMessage: (OFString*)text
128             sender: (OFString*)sender
129 {
130         BOOL first = bufferEmpty;
131         if (OF_UNLIKELY(bufferEmpty)) bufferEmpty = NO;
132
133         g_object_ref(chat_buffer);
134         g_idle_add_block(^{
135                 GtkTextIter endIter;
136                 if (OF_LIKELY(!first))
137                         gtk_text_buffer_insert_at_cursor(chat_buffer, "\n", 1);
138
139                 gtk_text_buffer_get_end_iter(chat_buffer, &endIter);
140                 gtk_text_buffer_insert_with_tags_by_name(chat_buffer, &endIter,
141                     [sender UTF8String], [sender UTF8StringLength], "bold",
142                     NULL);
143                 gtk_text_buffer_get_end_iter(chat_buffer, &endIter);
144                 gtk_text_buffer_insert_with_tags_by_name(chat_buffer, &endIter,
145                     ": ", 2, "bold", NULL);
146
147                 gtk_text_buffer_insert_at_cursor(chat_buffer, [text UTF8String],
148                     [text UTF8StringLength]);
149                 g_object_unref(chat_buffer);
150         });
151 }
152 @end