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