aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/event.c19
-rw-r--r--src/ui/chat.c15
-rw-r--r--src/ui/chat.h2
-rw-r--r--src/ui/message.c65
-rw-r--r--src/ui/message.h17
-rw-r--r--src/ui/new_contact.c2
-rw-r--r--src/ui/send_file.c176
-rw-r--r--src/ui/send_file.h6
8 files changed, 282 insertions, 20 deletions
diff --git a/src/event.c b/src/event.c
index c3e4ac6..2280785 100644
--- a/src/event.c
+++ b/src/event.c
@@ -190,7 +190,10 @@ event_joining_contact(MESSENGER_Application *app,
190 190
191 ui_chat_entry_update(handle, app, context); 191 ui_chat_entry_update(handle, app, context);
192 192
193 UI_MESSAGE_Handle *message = ui_message_new(UI_MESSAGE_STATUS); 193 UI_MESSAGE_Handle *message = ui_message_new(
194 UI_MESSAGE_STATUS,
195 UI_MESSAGE_CONTENT_TEXT
196 );
194 197
195 struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender( 198 struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender(
196 msg 199 msg
@@ -209,7 +212,7 @@ event_joining_contact(MESSENGER_Application *app,
209 message->message_box 212 message->message_box
210 ); 213 );
211 214
212 ui_message_delete(message); 215 handle->chat->messages = g_list_append(handle->chat->messages, message);
213} 216}
214 217
215void 218void
@@ -259,7 +262,10 @@ event_invitation(UNUSED MESSENGER_Application *app,
259 if (!invitation) 262 if (!invitation)
260 return; 263 return;
261 264
262 UI_MESSAGE_Handle *message = ui_message_new(UI_MESSAGE_STATUS); 265 UI_MESSAGE_Handle *message = ui_message_new(
266 UI_MESSAGE_STATUS,
267 UI_MESSAGE_CONTENT_TEXT
268 );
263 269
264 const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender( 270 const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender(
265 msg 271 msg
@@ -285,7 +291,7 @@ event_invitation(UNUSED MESSENGER_Application *app,
285 message->message_box 291 message->message_box
286 ); 292 );
287 293
288 ui_message_delete(message); 294 handle->chat->messages = g_list_append(handle->chat->messages, message);
289} 295}
290 296
291void 297void
@@ -301,7 +307,8 @@ event_receive_message(UNUSED MESSENGER_Application *app,
301 const int sent = GNUNET_CHAT_message_is_sent(msg); 307 const int sent = GNUNET_CHAT_message_is_sent(msg);
302 308
303 UI_MESSAGE_Handle *message = ui_message_new( 309 UI_MESSAGE_Handle *message = ui_message_new(
304 GNUNET_YES == sent? UI_MESSAGE_SENT : UI_MESSAGE_DEFAULT 310 GNUNET_YES == sent? UI_MESSAGE_SENT : UI_MESSAGE_DEFAULT,
311 UI_MESSAGE_CONTENT_TEXT
305 ); 312 );
306 313
307 const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender( 314 const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender(
@@ -329,7 +336,7 @@ event_receive_message(UNUSED MESSENGER_Application *app,
329 message->message_box 336 message->message_box
330 ); 337 );
331 338
332 ui_message_delete(message); 339 handle->chat->messages = g_list_append(handle->chat->messages, message);
333 340
334 gtk_label_set_text(handle->text_label, text? text : ""); 341 gtk_label_set_text(handle->text_label, text? text : "");
335 gtk_label_set_text(handle->timestamp_label, time? time : ""); 342 gtk_label_set_text(handle->timestamp_label, time? time : "");
diff --git a/src/ui/chat.c b/src/ui/chat.c
index a8547ba..42ccb9e 100644
--- a/src/ui/chat.c
+++ b/src/ui/chat.c
@@ -26,6 +26,7 @@
26 26
27#include <gdk/gdkkeysyms.h> 27#include <gdk/gdkkeysyms.h>
28 28
29#include "message.h"
29#include "messenger.h" 30#include "messenger.h"
30#include "picker.h" 31#include "picker.h"
31#include "profile_entry.h" 32#include "profile_entry.h"
@@ -252,6 +253,8 @@ ui_chat_new(MESSENGER_Application *app)
252 UI_CHAT_Handle *handle = g_malloc(sizeof(UI_CHAT_Handle)); 253 UI_CHAT_Handle *handle = g_malloc(sizeof(UI_CHAT_Handle));
253 UI_MESSENGER_Handle *messenger = &(app->ui.messenger); 254 UI_MESSENGER_Handle *messenger = &(app->ui.messenger);
254 255
256 handle->messages = NULL;
257
255 handle->builder = gtk_builder_new_from_file( 258 handle->builder = gtk_builder_new_from_file(
256 "resources/ui/chat.ui" 259 "resources/ui/chat.ui"
257 ); 260 );
@@ -552,5 +555,17 @@ ui_chat_delete(UI_CHAT_Handle *handle)
552 555
553 g_object_unref(handle->builder); 556 g_object_unref(handle->builder);
554 557
558 GList *list = handle->messages;
559
560 while (list) {
561 if (list->data)
562 ui_message_delete((UI_MESSAGE_Handle*) list->data);
563
564 list = list->next;
565 }
566
567 if (handle->messages)
568 g_list_free(handle->messages);
569
555 g_free(handle); 570 g_free(handle);
556} 571}
diff --git a/src/ui/chat.h b/src/ui/chat.h
index ae0880e..f065f61 100644
--- a/src/ui/chat.h
+++ b/src/ui/chat.h
@@ -36,6 +36,8 @@ typedef struct UI_PICKER_Handle UI_PICKER_Handle;
36 36
37typedef struct UI_CHAT_Handle 37typedef struct UI_CHAT_Handle
38{ 38{
39 GList *messages;
40
39 GtkBuilder *builder; 41 GtkBuilder *builder;
40 GtkWidget *chat_box; 42 GtkWidget *chat_box;
41 43
diff --git a/src/ui/message.c b/src/ui/message.c
index cacf666..4c89edb 100644
--- a/src/ui/message.c
+++ b/src/ui/message.c
@@ -27,7 +27,8 @@
27#include "../application.h" 27#include "../application.h"
28 28
29UI_MESSAGE_Handle* 29UI_MESSAGE_Handle*
30ui_message_new(UI_MESSAGE_Type type) 30ui_message_new(UI_MESSAGE_Type type,
31 UI_MESSAGE_ContentType content_type)
31{ 32{
32 UI_MESSAGE_Handle* handle = g_malloc(sizeof(UI_MESSAGE_Handle)); 33 UI_MESSAGE_Handle* handle = g_malloc(sizeof(UI_MESSAGE_Handle));
33 34
@@ -62,12 +63,16 @@ ui_message_new(UI_MESSAGE_Type type)
62 gtk_builder_get_object(handle->builder, "sender_label") 63 gtk_builder_get_object(handle->builder, "sender_label")
63 ); 64 );
64 65
65 handle->text_label = GTK_LABEL(
66 gtk_builder_get_object(handle->builder, "text_label")
67 );
68
69 if (UI_MESSAGE_STATUS == handle->type) 66 if (UI_MESSAGE_STATUS == handle->type)
70 { 67 {
68 handle->deny_revealer = GTK_REVEALER(
69 gtk_builder_get_object(handle->builder, "deny_revealer")
70 );
71
72 handle->accept_revealer = GTK_REVEALER(
73 gtk_builder_get_object(handle->builder, "accept_revealer")
74 );
75
71 handle->deny_button = GTK_BUTTON( 76 handle->deny_button = GTK_BUTTON(
72 gtk_builder_get_object(handle->builder, "deny_button") 77 gtk_builder_get_object(handle->builder, "deny_button")
73 ); 78 );
@@ -78,18 +83,64 @@ ui_message_new(UI_MESSAGE_Type type)
78 } 83 }
79 else 84 else
80 { 85 {
86 handle->deny_revealer = NULL;
87 handle->accept_revealer = NULL;
88
81 handle->deny_button = NULL; 89 handle->deny_button = NULL;
82 handle->accept_button = NULL; 90 handle->accept_button = NULL;
83 } 91 }
84 92
93 GtkContainer *content_box = GTK_CONTAINER(
94 gtk_builder_get_object(handle->builder, "content_box")
95 );
96
97 GtkBuilder *builder = gtk_builder_new_from_file(
98 "resources/ui/message_content.ui"
99 );
100
85 handle->timestamp_label = GTK_LABEL( 101 handle->timestamp_label = GTK_LABEL(
86 gtk_builder_get_object(handle->builder, "timestamp_label") 102 gtk_builder_get_object(builder, "timestamp_label")
87 ); 103 );
88 104
89 handle->read_receipt_image = GTK_IMAGE( 105 handle->read_receipt_image = GTK_IMAGE(
90 gtk_builder_get_object(handle->builder, "read_receipt_image") 106 gtk_builder_get_object(builder, "read_receipt_image")
107 );
108
109 handle->text_label = GTK_LABEL(
110 gtk_builder_get_object(builder, "text_label")
111 );
112
113 handle->file_revealer = GTK_REVEALER(
114 gtk_builder_get_object(builder, "file_revealer")
91 ); 115 );
92 116
117 handle->preview_drawing_area = GTK_DRAWING_AREA(
118 gtk_builder_get_object(builder, "preview_drawing_area")
119 );
120
121 switch (handle->type)
122 {
123 case UI_MESSAGE_STATUS:
124 gtk_widget_set_visible(GTK_WIDGET(handle->timestamp_label), FALSE);
125 break;
126 default:
127 break;
128 }
129
130 switch (content_type)
131 {
132 case UI_MESSAGE_CONTENT_FILE:
133 gtk_revealer_set_reveal_child(handle->file_revealer, TRUE);
134 break;
135 default:
136 break;
137 }
138
139 gtk_container_add(content_box, GTK_WIDGET(
140 gtk_builder_get_object(builder, "message_content_box")
141 ));
142
143 g_object_unref(builder);
93 return handle; 144 return handle;
94} 145}
95 146
diff --git a/src/ui/message.h b/src/ui/message.h
index a17247c..b380960 100644
--- a/src/ui/message.h
+++ b/src/ui/message.h
@@ -39,6 +39,13 @@ typedef enum UI_MESSAGE_Type
39 UI_MESSAGE_STATUS = 2 39 UI_MESSAGE_STATUS = 2
40} UI_MESSAGE_Type; 40} UI_MESSAGE_Type;
41 41
42typedef enum UI_MESSAGE_ContentType
43{
44 UI_MESSAGE_CONTENT_TEXT = 0,
45 UI_MESSAGE_CONTENT_FILE = 1,
46 UI_MESSAGE_CONTENT_PREVIEW = 2
47} UI_MESSAGE_ContentType;
48
42typedef struct UI_MESSAGE_Handle 49typedef struct UI_MESSAGE_Handle
43{ 50{
44 UI_MESSAGE_Type type; 51 UI_MESSAGE_Type type;
@@ -49,17 +56,23 @@ typedef struct UI_MESSAGE_Handle
49 HdyAvatar *sender_avatar; 56 HdyAvatar *sender_avatar;
50 GtkLabel *sender_label; 57 GtkLabel *sender_label;
51 58
52 GtkLabel *text_label; 59 GtkRevealer *deny_revealer;
60 GtkRevealer *accept_revealer;
53 61
54 GtkButton *deny_button; 62 GtkButton *deny_button;
55 GtkButton *accept_button; 63 GtkButton *accept_button;
56 64
57 GtkLabel *timestamp_label; 65 GtkLabel *timestamp_label;
58 GtkImage *read_receipt_image; 66 GtkImage *read_receipt_image;
67
68 GtkLabel *text_label;
69 GtkRevealer *file_revealer;
70 GtkDrawingArea *preview_drawing_area;
59} UI_MESSAGE_Handle; 71} UI_MESSAGE_Handle;
60 72
61UI_MESSAGE_Handle* 73UI_MESSAGE_Handle*
62ui_message_new(UI_MESSAGE_Type type); 74ui_message_new(UI_MESSAGE_Type type,
75 UI_MESSAGE_ContentType content_type);
63 76
64void 77void
65ui_message_delete(UI_MESSAGE_Handle *handle); 78ui_message_delete(UI_MESSAGE_Handle *handle);
diff --git a/src/ui/new_contact.c b/src/ui/new_contact.c
index 3acae1a..7e6f9c6 100644
--- a/src/ui/new_contact.c
+++ b/src/ui/new_contact.c
@@ -69,7 +69,7 @@ handle_id_drawing_area_draw(GtkWidget* drawing_area,
69 GdkPixbuf *image = NULL; 69 GdkPixbuf *image = NULL;
70 70
71 if (!handle->image) 71 if (!handle->image)
72 goto render_image; 72 return FALSE;
73 73
74 uint w, h; 74 uint w, h;
75 zbar_image_get_size(handle->image, &w, &h); 75 zbar_image_get_size(handle->image, &w, &h);
diff --git a/src/ui/send_file.c b/src/ui/send_file.c
index cde2c4d..2d3f4a6 100644
--- a/src/ui/send_file.c
+++ b/src/ui/send_file.c
@@ -71,6 +71,146 @@ handle_dialog_destroy(UNUSED GtkWidget *window,
71 ui_send_file_dialog_cleanup((UI_SEND_FILE_Handle*) user_data); 71 ui_send_file_dialog_cleanup((UI_SEND_FILE_Handle*) user_data);
72} 72}
73 73
74static int
75handle_file_redraw_animation(gpointer user_data)
76{
77 UI_SEND_FILE_Handle *handle = (UI_SEND_FILE_Handle*) user_data;
78
79 handle->redraw_animation = 0;
80
81 if (handle->file_drawing_area)
82 gtk_widget_queue_draw(GTK_WIDGET(handle->file_drawing_area));
83
84 return FALSE;
85}
86
87static gboolean
88handle_file_drawing_area_draw(GtkWidget* drawing_area,
89 cairo_t* cairo,
90 gpointer user_data)
91{
92 UI_SEND_FILE_Handle *handle = (UI_SEND_FILE_Handle*) user_data;
93
94 GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
95
96 const guint width = gtk_widget_get_allocated_width(drawing_area);
97 const guint height = gtk_widget_get_allocated_height(drawing_area);
98
99 gtk_render_background(context, cairo, 0, 0, width, height);
100
101 GdkPixbuf *image = handle->image;
102
103 if (!handle->animation)
104 goto render_image;
105
106 if (handle->animation_iter)
107 gdk_pixbuf_animation_iter_advance(handle->animation_iter, NULL);
108 else
109 handle->animation_iter = gdk_pixbuf_animation_get_iter(
110 handle->animation, NULL
111 );
112
113 image = gdk_pixbuf_animation_iter_get_pixbuf(handle->animation_iter);
114
115 const int delay = gdk_pixbuf_animation_iter_get_delay_time(
116 handle->animation_iter
117 );
118
119 handle->redraw_animation = g_timeout_add(
120 delay, handle_file_redraw_animation, handle
121 );
122
123render_image:
124 if (!image)
125 return FALSE;
126
127 int dwidth = gdk_pixbuf_get_width(image);
128 int dheight = gdk_pixbuf_get_height(image);
129
130 double ratio_width = 1.0 * width / dwidth;
131 double ratio_height = 1.0 * height / dheight;
132
133 const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
134
135 dwidth = (int) (dwidth * ratio);
136 dheight = (int) (dheight * ratio);
137
138 double dx = (width - dwidth) * 0.5;
139 double dy = (height - dheight) * 0.5;
140
141 const int interp_type = (ratio >= 1.0?
142 GDK_INTERP_NEAREST :
143 GDK_INTERP_BILINEAR
144 );
145
146 GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
147 image,
148 dwidth,
149 dheight,
150 interp_type
151 );
152
153 gtk_render_icon(context, cairo, scaled, dx, dy);
154
155 cairo_fill(cairo);
156
157 g_object_unref(scaled);
158 return FALSE;
159}
160
161static void
162_clear_file_preview_data(UI_SEND_FILE_Handle *handle)
163{
164 if (handle->image)
165 {
166 g_object_unref(handle->image);
167 handle->image = NULL;
168 }
169
170 if (handle->redraw_animation)
171 {
172 g_source_remove(handle->redraw_animation);
173 handle->redraw_animation = 0;
174 }
175
176 if (handle->animation_iter)
177 {
178 g_object_unref(handle->animation_iter);
179 handle->animation_iter = NULL;
180 }
181
182 if (handle->animation)
183 {
184 g_object_unref(handle->animation);
185 handle->animation = NULL;
186 }
187}
188
189static void
190handle_file_chooser_button_file_set(GtkFileChooserButton *file_chooser_button,
191 gpointer user_data)
192{
193 UI_SEND_FILE_Handle *handle = (UI_SEND_FILE_Handle*) user_data;
194
195 _clear_file_preview_data(handle);
196
197 char *filename = gtk_file_chooser_get_filename(
198 GTK_FILE_CHOOSER(file_chooser_button)
199 );
200
201 if (filename)
202 {
203 handle->animation = gdk_pixbuf_animation_new_from_file(filename, NULL);
204
205 if (!handle->animation)
206 handle->image = gdk_pixbuf_new_from_file(filename, NULL);
207
208 g_free(filename);
209 }
210
211 gtk_widget_queue_draw(GTK_WIDGET(handle->file_drawing_area));
212}
213
74void 214void
75ui_send_file_dialog_init(MESSENGER_Application *app, 215ui_send_file_dialog_init(MESSENGER_Application *app,
76 UI_SEND_FILE_Handle *handle) 216 UI_SEND_FILE_Handle *handle)
@@ -99,6 +239,20 @@ ui_send_file_dialog_init(MESSENGER_Application *app,
99 gtk_builder_get_object(handle->builder, "file_chooser_button") 239 gtk_builder_get_object(handle->builder, "file_chooser_button")
100 ); 240 );
101 241
242 g_signal_connect(
243 handle->file_drawing_area,
244 "draw",
245 G_CALLBACK(handle_file_drawing_area_draw),
246 handle
247 );
248
249 g_signal_connect(
250 handle->file_chooser_button,
251 "file-set",
252 G_CALLBACK(handle_file_chooser_button_file_set),
253 handle
254 );
255
102 handle->cancel_button = GTK_BUTTON( 256 handle->cancel_button = GTK_BUTTON(
103 gtk_builder_get_object(handle->builder, "cancel_button") 257 gtk_builder_get_object(handle->builder, "cancel_button")
104 ); 258 );
@@ -127,22 +281,36 @@ ui_send_file_dialog_init(MESSENGER_Application *app,
127 G_CALLBACK(handle_dialog_destroy), 281 G_CALLBACK(handle_dialog_destroy),
128 handle 282 handle
129 ); 283 );
284
285 handle->image = NULL;
286 handle->animation = NULL;
287 handle->animation_iter = NULL;
288
289 handle->redraw_animation = 0;
130} 290}
131 291
132void 292void
133ui_send_file_dialog_update(UI_SEND_FILE_Handle *handle, 293ui_send_file_dialog_update(UI_SEND_FILE_Handle *handle,
134 const gchar *filename) 294 const gchar *filename)
135{ 295{
136 if ((!filename) || (!gtk_file_chooser_set_filename( 296 if (!handle->file_chooser_button)
137 GTK_FILE_CHOOSER(handle->file_chooser_button),
138 filename)))
139 return; 297 return;
140 298
141 // TODO: update preview 299 gtk_file_chooser_set_filename(
300 GTK_FILE_CHOOSER(handle->file_chooser_button),
301 filename
302 );
303
304 handle_file_chooser_button_file_set(
305 handle->file_chooser_button,
306 handle
307 );
142} 308}
143 309
144void 310void
145ui_send_file_dialog_cleanup(UI_SEND_FILE_Handle *handle) 311ui_send_file_dialog_cleanup(UI_SEND_FILE_Handle *handle)
146{ 312{
313 _clear_file_preview_data(handle);
314
147 g_object_unref(handle->builder); 315 g_object_unref(handle->builder);
148} 316}
diff --git a/src/ui/send_file.h b/src/ui/send_file.h
index cb58285..1a68681 100644
--- a/src/ui/send_file.h
+++ b/src/ui/send_file.h
@@ -39,6 +39,12 @@ typedef struct UI_SEND_FILE_Handle
39 39
40 GtkButton *cancel_button; 40 GtkButton *cancel_button;
41 GtkButton *send_button; 41 GtkButton *send_button;
42
43 GdkPixbuf *image;
44 GdkPixbufAnimation *animation;
45 GdkPixbufAnimationIter *animation_iter;
46
47 guint redraw_animation;
42} UI_SEND_FILE_Handle; 48} UI_SEND_FILE_Handle;
43 49
44void 50void