diff options
Diffstat (limited to 'src/ui/message.c')
-rw-r--r-- | src/ui/message.c | 217 |
1 files changed, 216 insertions, 1 deletions
diff --git a/src/ui/message.c b/src/ui/message.c index da6bb97..4aa7a85 100644 --- a/src/ui/message.c +++ b/src/ui/message.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2021 GNUnet e.V. | 3 | Copyright (C) 2021--2022 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | under the terms of the GNU Affero General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
@@ -24,8 +24,143 @@ | |||
24 | 24 | ||
25 | #include "message.h" | 25 | #include "message.h" |
26 | 26 | ||
27 | #include <gnunet/gnunet_chat_lib.h> | ||
28 | |||
27 | #include "../application.h" | 29 | #include "../application.h" |
28 | 30 | ||
31 | static int | ||
32 | handle_message_redraw_animation(gpointer user_data) | ||
33 | { | ||
34 | UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data; | ||
35 | |||
36 | handle->redraw_animation = 0; | ||
37 | |||
38 | if ((handle->preview_drawing_area) && | ||
39 | ((handle->preview_image) || | ||
40 | (handle->preview_animation) || | ||
41 | (handle->preview_animation_iter))) | ||
42 | gtk_widget_queue_draw(GTK_WIDGET(handle->preview_drawing_area)); | ||
43 | |||
44 | return FALSE; | ||
45 | } | ||
46 | |||
47 | static gboolean | ||
48 | handle_preview_drawing_area_draw(GtkWidget* drawing_area, | ||
49 | cairo_t* cairo, | ||
50 | gpointer user_data) | ||
51 | { | ||
52 | UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data; | ||
53 | |||
54 | GtkStyleContext* context = gtk_widget_get_style_context(drawing_area); | ||
55 | |||
56 | const guint width = gtk_widget_get_allocated_width(drawing_area); | ||
57 | const guint height = gtk_widget_get_allocated_height(drawing_area); | ||
58 | |||
59 | gtk_render_background(context, cairo, 0, 0, width, height); | ||
60 | |||
61 | GdkPixbuf *image = handle->preview_image; | ||
62 | |||
63 | if (!(handle->preview_animation)) | ||
64 | goto render_image; | ||
65 | |||
66 | if (handle->preview_animation_iter) | ||
67 | gdk_pixbuf_animation_iter_advance(handle->preview_animation_iter, NULL); | ||
68 | else | ||
69 | handle->preview_animation_iter = gdk_pixbuf_animation_get_iter( | ||
70 | handle->preview_animation, NULL | ||
71 | ); | ||
72 | |||
73 | image = gdk_pixbuf_animation_iter_get_pixbuf(handle->preview_animation_iter); | ||
74 | |||
75 | const int delay = gdk_pixbuf_animation_iter_get_delay_time( | ||
76 | handle->preview_animation_iter | ||
77 | ); | ||
78 | |||
79 | handle->redraw_animation = g_timeout_add( | ||
80 | delay, handle_message_redraw_animation, handle | ||
81 | ); | ||
82 | |||
83 | render_image: | ||
84 | if (!image) | ||
85 | return FALSE; | ||
86 | |||
87 | int dwidth = gdk_pixbuf_get_width(image); | ||
88 | int dheight = gdk_pixbuf_get_height(image); | ||
89 | |||
90 | gint optimal_height = width * dheight / dwidth; | ||
91 | |||
92 | gtk_widget_set_size_request( | ||
93 | GTK_WIDGET(drawing_area), | ||
94 | width, | ||
95 | optimal_height | ||
96 | ); | ||
97 | |||
98 | double ratio_width = 1.0 * width / dwidth; | ||
99 | double ratio_height = 1.0 * height / dheight; | ||
100 | |||
101 | const double ratio = ratio_width < ratio_height? ratio_width : ratio_height; | ||
102 | |||
103 | dwidth = (int) (dwidth * ratio); | ||
104 | dheight = (int) (dheight * ratio); | ||
105 | |||
106 | double dx = (width - dwidth) * 0.5; | ||
107 | double dy = (height - dheight) * 0.5; | ||
108 | |||
109 | const int interp_type = (ratio >= 1.0? | ||
110 | GDK_INTERP_NEAREST : | ||
111 | GDK_INTERP_BILINEAR | ||
112 | ); | ||
113 | |||
114 | GdkPixbuf* scaled = gdk_pixbuf_scale_simple( | ||
115 | image, | ||
116 | dwidth, | ||
117 | dheight, | ||
118 | interp_type | ||
119 | ); | ||
120 | |||
121 | gtk_render_icon(context, cairo, scaled, dx, dy); | ||
122 | |||
123 | cairo_fill(cairo); | ||
124 | |||
125 | g_object_unref(scaled); | ||
126 | return FALSE; | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | _clear_message_preview_data(UI_MESSAGE_Handle *handle) | ||
131 | { | ||
132 | if (handle->preview_image) | ||
133 | { | ||
134 | g_object_unref(handle->preview_image); | ||
135 | handle->preview_image = NULL; | ||
136 | } | ||
137 | |||
138 | if (handle->redraw_animation) | ||
139 | { | ||
140 | g_source_remove(handle->redraw_animation); | ||
141 | handle->redraw_animation = 0; | ||
142 | } | ||
143 | |||
144 | if (handle->preview_animation_iter) | ||
145 | { | ||
146 | g_object_unref(handle->preview_animation_iter); | ||
147 | handle->preview_animation_iter = NULL; | ||
148 | } | ||
149 | |||
150 | if (handle->preview_animation) | ||
151 | { | ||
152 | g_object_unref(handle->preview_animation); | ||
153 | handle->preview_animation = NULL; | ||
154 | } | ||
155 | |||
156 | if (handle->preview_drawing_area) | ||
157 | gtk_widget_set_size_request( | ||
158 | GTK_WIDGET(handle->preview_drawing_area), | ||
159 | -1, | ||
160 | -1 | ||
161 | ); | ||
162 | } | ||
163 | |||
29 | UI_MESSAGE_Handle* | 164 | UI_MESSAGE_Handle* |
30 | ui_message_new(MESSENGER_Application *app, | 165 | ui_message_new(MESSENGER_Application *app, |
31 | UI_MESSAGE_Type type) | 166 | UI_MESSAGE_Type type) |
@@ -120,10 +255,33 @@ ui_message_new(MESSENGER_Application *app, | |||
120 | gtk_builder_get_object(builder, "file_revealer") | 255 | gtk_builder_get_object(builder, "file_revealer") |
121 | ); | 256 | ); |
122 | 257 | ||
258 | handle->filename_label = GTK_LABEL( | ||
259 | gtk_builder_get_object(builder, "filename_label") | ||
260 | ); | ||
261 | |||
262 | handle->file_progress_bar = GTK_PROGRESS_BAR( | ||
263 | gtk_builder_get_object(builder, "file_progress_bar") | ||
264 | ); | ||
265 | |||
266 | handle->file_button = GTK_BUTTON( | ||
267 | gtk_builder_get_object(builder, "file_button") | ||
268 | ); | ||
269 | |||
270 | handle->file_status_image = GTK_IMAGE( | ||
271 | gtk_builder_get_object(builder, "file_status_image") | ||
272 | ); | ||
273 | |||
123 | handle->preview_drawing_area = GTK_DRAWING_AREA( | 274 | handle->preview_drawing_area = GTK_DRAWING_AREA( |
124 | gtk_builder_get_object(builder, "preview_drawing_area") | 275 | gtk_builder_get_object(builder, "preview_drawing_area") |
125 | ); | 276 | ); |
126 | 277 | ||
278 | handle->preview_draw_signal = g_signal_connect( | ||
279 | handle->preview_drawing_area, | ||
280 | "draw", | ||
281 | G_CALLBACK(handle_preview_drawing_area_draw), | ||
282 | handle | ||
283 | ); | ||
284 | |||
127 | switch (handle->type) | 285 | switch (handle->type) |
128 | { | 286 | { |
129 | case UI_MESSAGE_STATUS: | 287 | case UI_MESSAGE_STATUS: |
@@ -138,6 +296,13 @@ ui_message_new(MESSENGER_Application *app, | |||
138 | )); | 296 | )); |
139 | 297 | ||
140 | g_object_unref(builder); | 298 | g_object_unref(builder); |
299 | |||
300 | handle->preview_image = NULL; | ||
301 | handle->preview_animation = NULL; | ||
302 | handle->preview_animation_iter = NULL; | ||
303 | |||
304 | handle->redraw_animation = 0; | ||
305 | |||
141 | return handle; | 306 | return handle; |
142 | } | 307 | } |
143 | 308 | ||
@@ -150,6 +315,49 @@ ui_message_update(UI_MESSAGE_Handle *handle, | |||
150 | if (!file) | 315 | if (!file) |
151 | return; | 316 | return; |
152 | 317 | ||
318 | if (GNUNET_YES != GNUNET_CHAT_file_is_local(file)) | ||
319 | goto file_content; | ||
320 | |||
321 | if (!(handle->preview_drawing_area)) | ||
322 | goto file_progress; | ||
323 | |||
324 | const char *preview = GNUNET_CHAT_file_open_preview(file); | ||
325 | |||
326 | if (!preview) | ||
327 | goto file_progress; | ||
328 | |||
329 | handle->preview_animation = gdk_pixbuf_animation_new_from_file( | ||
330 | preview, NULL | ||
331 | ); | ||
332 | |||
333 | if (!(handle->preview_animation)) | ||
334 | handle->preview_image = gdk_pixbuf_new_from_file(preview, NULL); | ||
335 | |||
336 | if ((handle->preview_animation) || (handle->preview_animation)) | ||
337 | { | ||
338 | gtk_widget_set_size_request( | ||
339 | GTK_WIDGET(handle->preview_drawing_area), | ||
340 | 250, | ||
341 | -1 | ||
342 | ); | ||
343 | |||
344 | gtk_stack_set_visible_child( | ||
345 | handle->content_stack, | ||
346 | GTK_WIDGET(handle->preview_drawing_area) | ||
347 | ); | ||
348 | |||
349 | gtk_widget_queue_draw(GTK_WIDGET(handle->preview_drawing_area)); | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | GNUNET_CHAT_file_close_preview(file); | ||
354 | |||
355 | file_progress: | ||
356 | gtk_progress_bar_set_fraction(handle->file_progress_bar, 1.0); | ||
357 | |||
358 | file_content: | ||
359 | gtk_label_set_text(handle->filename_label, GNUNET_CHAT_file_get_name(file)); | ||
360 | |||
153 | gtk_stack_set_visible_child( | 361 | gtk_stack_set_visible_child( |
154 | handle->content_stack, | 362 | handle->content_stack, |
155 | GTK_WIDGET(handle->file_revealer) | 363 | GTK_WIDGET(handle->file_revealer) |
@@ -161,6 +369,13 @@ ui_message_update(UI_MESSAGE_Handle *handle, | |||
161 | void | 369 | void |
162 | ui_message_delete(UI_MESSAGE_Handle *handle) | 370 | ui_message_delete(UI_MESSAGE_Handle *handle) |
163 | { | 371 | { |
372 | _clear_message_preview_data(handle); | ||
373 | |||
374 | g_signal_handler_disconnect( | ||
375 | handle->preview_drawing_area, | ||
376 | handle->preview_draw_signal | ||
377 | ); | ||
378 | |||
164 | g_object_unref(handle->builder); | 379 | g_object_unref(handle->builder); |
165 | 380 | ||
166 | g_free(handle); | 381 | g_free(handle); |