]> cgit.babelmonkeys.de Git - jubjub.git/blob - src/gui/gtk/JubGtkChatUI.m
JubGtkChat: Refer to the correct version of the close and send blocks
[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 void call_send_block(GtkEntry *entry, gpointer data)
10 {
11         struct call_send_block_params *params = data;
12
13         OFString *text =
14             [[OFString alloc] initWithUTF8String: gtk_entry_get_text(entry)];
15
16         if ([text length] > 0) {
17                 gtk_entry_set_text(entry, "");
18                 params->block(text);
19                 [params->chat addMessage: text
20                                   sender: @"You"];
21         }
22
23         [text release];
24 }
25
26 static void call_close_block(GtkWidget *object, gpointer data)
27 {
28         jub_close_block_t block = data;
29         block();
30 }
31
32 @implementation JubGtkChatUI
33 - initWithTitle: (OFString*)title
34      closeBlock: (jub_close_block_t)closeBlock
35       sendBlock: (jub_send_block_t)sendBlock
36 {
37         self = [super init];
38
39         @try {
40                 __block volatile BOOL initialized = NO;
41                 __block GtkWidget *chat_window;
42                 __block GtkTextBuffer *chat_buffer;
43
44                 _closeBlock = [closeBlock copy];
45                 _sendBlock = [sendBlock copy];
46                 _bufferEmpty = YES;
47
48                 g_idle_add_block(^{
49                         GtkEntry *chat_entry;
50
51                         GtkBuilder *builder = gtk_builder_new();
52                         gtk_builder_add_from_file(builder, "data/gtk/chat.ui",
53                             NULL);
54
55                         chat_window = GTK_WIDGET(
56                             gtk_builder_get_object(builder, "ChatWindow"));
57                         g_signal_connect(chat_window, "destroy",
58                             G_CALLBACK(call_close_block), _closeBlock);
59
60                         _chat_view = GTK_TEXT_VIEW(
61                             gtk_builder_get_object(builder, "ChatTextView"));
62                         chat_buffer = gtk_text_view_get_buffer(_chat_view);
63                         gtk_text_buffer_create_tag(chat_buffer, "bold",
64                             "weight", PANGO_WEIGHT_BOLD, NULL);
65
66                         chat_entry = GTK_ENTRY(
67                             gtk_builder_get_object(builder, "ChatEntry"));
68                         struct call_send_block_params *send_params =
69                             [self allocMemoryWithSize: sizeof(*send_params)];
70                         send_params->block = _sendBlock;
71                         send_params->chat = self;
72                         g_signal_connect(chat_entry, "activate",
73                             G_CALLBACK(call_send_block), send_params);
74
75                         gtk_window_set_title(GTK_WINDOW(chat_window),
76                             [title UTF8String]);
77                         gtk_widget_show(chat_window);
78
79                         initialized = YES;
80
81                         g_object_unref(builder);
82                 });
83
84                 while (!initialized);
85
86                 _chat_buffer = chat_buffer;
87                 _chat_window = chat_window;
88         } @catch (id e) {
89                 [self release];
90                 @throw e;
91         }
92
93         return self;
94 }
95
96 - (void)dealloc
97 {
98         gtk_widget_destroy(_chat_window);
99         [_sendBlock release];
100         [_closeBlock release];
101
102         [super dealloc];
103 }
104
105 - (void)addMessage: (OFString*)text
106             sender: (OFString*)sender
107 {
108         BOOL first = _bufferEmpty;
109         if (OF_UNLIKELY(_bufferEmpty)) _bufferEmpty = NO;
110
111         g_idle_add_block(^{
112                 GtkTextIter end_iter;
113                 GtkTextMark *insert_mark =
114                     gtk_text_buffer_get_insert(_chat_buffer);
115
116                 if (OF_LIKELY(!first))
117                         gtk_text_buffer_insert_at_cursor(_chat_buffer, "\n", 1);
118
119                 gtk_text_buffer_get_end_iter(_chat_buffer, &end_iter);
120                 gtk_text_buffer_insert_with_tags_by_name(_chat_buffer,
121                     &end_iter, [sender UTF8String], [sender UTF8StringLength],
122                     "bold", NULL);
123                 gtk_text_buffer_get_end_iter(_chat_buffer, &end_iter);
124                 gtk_text_buffer_insert_with_tags_by_name(_chat_buffer,
125                     &end_iter, ": ", 2, "bold", NULL);
126
127                 gtk_text_buffer_insert_at_cursor(_chat_buffer,
128                     [text UTF8String], [text UTF8StringLength]);
129
130                 gtk_text_view_scroll_to_mark(_chat_view, insert_mark, 0,
131                     FALSE, 0, 0);
132         });
133 }
134 @end